File size: 11,602 Bytes
ac4a6d6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
import React, { useState, Suspense } from 'react';
import { HashRouter, Routes, Route, useNavigate, Navigate } from 'react-router-dom';
import {
  FileText, FileUp, Clock, LogOut, Loader2, CheckCircle2,
  Shield, Activity, Lock, Terminal
} from 'lucide-react';
import { Header } from './components/Header';
import { Sidebar } from './components/Sidebar';
import { RedactionCard } from './components/RedactionCard';
import { useThemeStore } from './store/theme';

// Lazy loading components for code splitting & bundle reduction
const TextRedaction = React.lazy(() => import('./pages/TextRedaction').then(m => ({ default: m.TextRedaction })));
const PDFRedaction = React.lazy(() => import('./pages/PDFRedaction').then(m => ({ default: m.PDFRedaction })));
const History = React.lazy(() => import('./pages/History').then(m => ({ default: m.History })));
const AccountDetails = React.lazy(() => import('./pages/AccountDetails').then(m => ({ default: m.AccountDetails })));
const HowToUse = React.lazy(() => import('./pages/HowToUse').then(m => ({ default: m.HowToUse })));
const AboutUs = React.lazy(() => import('./pages/AboutUs').then(m => ({ default: m.AboutUs })));
const ContactUs = React.lazy(() => import('./pages/ContactUs').then(m => ({ default: m.ContactUs })));
const RegisterPage = React.lazy(() => import('./pages/Register'));
const LoginPage = React.lazy(() => import('./pages/Login'));
const LandingPage = React.lazy(() => import('./pages/Landing').then(m => ({ default: m.Landing })));

function PageLoader() {
  return (
    <div className="min-h-[70vh] flex flex-col items-center justify-center text-slate-400 font-sans">
      <Loader2 className="w-8 h-8 animate-spin text-red-500 mb-3" />
      <p className="text-sm font-mono tracking-wider uppercase">Loading Module...</p>
    </div>
  );
}

function ProtectedRoute({ children }: { children: React.ReactElement }) {
  const token = localStorage.getItem('token');
  if (!token) {
    return <Navigate to="/landing" replace />;
  }
  return children;
}

function Home() {
  const navigate = useNavigate();
  const redactionOptions = [
    {
      icon: FileText,
      title: 'Text Redaction',
      description: 'Obfuscate PII, Indian numbers, names, and custom confidential text in real-time.',
      path: '/text-redaction',
    },
    {
      icon: FileUp,
      title: 'File Redaction',
      description: 'Sanitize PDF documents, Word files, Excel spreadsheets, and scanned images offline.',
      path: '/pdf-redaction',
    },
    {
      icon: Clock,
      title: 'History',
      description: 'Review your recent redaction logs and processed files stored in local memory.',
      path: '/history',
    },
  ];

  const handleLogout = () => {
    localStorage.removeItem('token');
    window.location.href = '/#/login';
  };

  return (
    <main className="pt-24 px-6 pb-16 max-w-6xl mx-auto font-sans relative overflow-hidden">
      {/* Dynamic Ambient Background Animations */}
      <div className="absolute top-10 left-1/2 -translate-x-1/2 w-[800px] h-[300px] bg-gradient-to-r from-red-600/15 via-red-900/10 to-blue-600/10 blur-3xl pointer-events-none -z-10 animate-pulse" />
      <div className="absolute top-1/3 right-10 w-72 h-72 bg-red-500/10 rounded-full blur-2xl pointer-events-none -z-10 animate-bounce duration-1000" />
      <div className="absolute inset-0 bg-[linear-gradient(to_right,#1e293b10_1px,transparent_1px),linear-gradient(to_bottom,#1e293b10_1px,transparent_1px)] bg-[size:3rem_3rem] pointer-events-none -z-20" />

      {/* Hero Welcome Banner */}
      <div className="bg-slate-900/80 border border-slate-800 backdrop-blur-md p-8 rounded-sm mb-10 shadow-2xl relative overflow-hidden group hover:border-slate-700 transition-all">
        <div className="absolute -right-10 -bottom-10 w-48 h-48 bg-red-600/10 rounded-full blur-2xl group-hover:bg-red-600/20 transition-all pointer-events-none" />

        <div className="flex flex-col md:flex-row justify-between items-start md:items-center gap-6 relative z-10">
          <div className="space-y-3">
            <div className="inline-flex items-center gap-2 px-3 py-1 rounded-sm bg-red-950/60 border border-red-500/30 text-red-400 text-xs font-mono font-bold tracking-wider uppercase">
              <Shield className="w-3.5 h-3.5 text-red-500 animate-pulse" />
              <span>Security Console Active</span>
            </div>
            <h1 className="text-3xl md:text-4xl font-extrabold text-white tracking-tight font-sans">
              Welcome to <span className="text-red-500 underline decoration-red-600/50 underline-offset-4">RE-DACT</span>
            </h1>
            <p className="text-sm text-slate-400 max-w-2xl leading-relaxed">
              Your localized workspace for stripping sensitive personal identifiers, Indian regulatory numbers, and financial data using advanced offline NLP and synthetic anonymization.
            </p>
          </div>

          <button
            onClick={handleLogout}
            className="flex items-center gap-2 px-5 py-2.5 text-xs font-mono uppercase font-bold text-red-400 bg-slate-950 hover:bg-red-950/40 border border-slate-800 hover:border-red-900/60 rounded-sm transition-all shrink-0 shadow-lg"
          >
            <LogOut className="w-4 h-4" />
            <span>Logout Account</span>
          </button>
        </div>

        {/* Live Status Indicators */}
        <div className="grid grid-cols-2 sm:grid-cols-4 gap-4 mt-8 pt-6 border-t border-slate-800/80 font-mono text-xs">
          <div className="flex items-center gap-2.5 text-slate-300">
            <span className="w-2 h-2 rounded-full bg-emerald-500 animate-ping" />
            <span className="font-bold">100% Offline </span>
          </div>
          <div className="flex items-center gap-2.5 text-slate-300">
            <CheckCircle2 className="w-4 h-4 text-blue-400 shrink-0" />
            <span>Trained and Finetuned Models</span>
          </div>
          <div className="flex items-center gap-2.5 text-slate-300">
            <Lock className="w-4 h-4 text-red-400 shrink-0" />
            <span>Zero Data Retention</span>
          </div>
          <div className="flex items-center gap-2.5 text-slate-300">
            <Activity className="w-4 h-4 text-emerald-400 shrink-0" />
            <span>5 Redaction Levels</span>
          </div>
        </div>
      </div>

      {/* Module Selection Section */}
      <div className="space-y-4">
        <div className="flex items-center justify-between border-b border-slate-800/80 pb-3">
          <h2 className="text-lg font-bold text-white tracking-wide uppercase font-mono flex items-center gap-2">
            <Terminal className="w-4 h-4 text-red-500" />
            Select Sanitization Module
          </h2>
          <span className="text-xs text-slate-500 font-mono">Choose a module to launch</span>
        </div>

        <div className="grid grid-cols-1 md:grid-cols-3 gap-6 pt-2">
          {redactionOptions.map((option) => (
            <RedactionCard
              key={option.title}
              icon={option.icon}
              title={option.title}
              description={option.description}
              onClick={() => navigate(option.path)}
            />
          ))}
        </div>
      </div>
    </main>
  );
}

function App() {
  const [isSidebarOpen, setIsSidebarOpen] = useState(false);
  const { theme } = useThemeStore();

  return (
    <HashRouter>
      <div className={theme}>
        <div className="min-h-screen bg-slate-950 text-slate-100 selection:bg-red-600 selection:text-white font-sans">
          <Suspense fallback={<PageLoader />}>
            <Routes>
              <Route
                path="/home"
                element={
                  <ProtectedRoute>
                    <>
                      <Header onMenuClick={() => setIsSidebarOpen(true)} />
                      <Sidebar isOpen={isSidebarOpen} onClose={() => setIsSidebarOpen(false)} />
                      <Home />
                    </>
                  </ProtectedRoute>
                }
              />
              <Route path="/" element={<Navigate to="/home" replace />} />
              <Route
                path="/text-redaction"
                element={
                  <ProtectedRoute>
                    <>
                      <Header onMenuClick={() => setIsSidebarOpen(true)} />
                      <Sidebar isOpen={isSidebarOpen} onClose={() => setIsSidebarOpen(false)} />
                      <TextRedaction />
                    </>
                  </ProtectedRoute>
                }
              />
              <Route
                path="/pdf-redaction"
                element={
                  <ProtectedRoute>
                    <>
                      <Header onMenuClick={() => setIsSidebarOpen(true)} />
                      <Sidebar isOpen={isSidebarOpen} onClose={() => setIsSidebarOpen(false)} />
                      <PDFRedaction />
                    </>
                  </ProtectedRoute>
                }
              />
              <Route
                path="/history"
                element={
                  <ProtectedRoute>
                    <>
                      <Header onMenuClick={() => setIsSidebarOpen(true)} />
                      <Sidebar isOpen={isSidebarOpen} onClose={() => setIsSidebarOpen(false)} />
                      <History />
                    </>
                  </ProtectedRoute>
                }
              />
              <Route
                path="/account-details"
                element={
                  <ProtectedRoute>
                    <>
                      <Header onMenuClick={() => setIsSidebarOpen(true)} />
                      <Sidebar isOpen={isSidebarOpen} onClose={() => setIsSidebarOpen(false)} />
                      <AccountDetails />
                    </>
                  </ProtectedRoute>
                }
              />
              <Route
                path="/how-to-use"
                element={
                  <ProtectedRoute>
                    <>
                      <Header onMenuClick={() => setIsSidebarOpen(true)} />
                      <Sidebar isOpen={isSidebarOpen} onClose={() => setIsSidebarOpen(false)} />
                      <HowToUse />
                    </>
                  </ProtectedRoute>
                }
              />
              <Route
                path="/about-us"
                element={
                  <ProtectedRoute>
                    <>
                      <Header onMenuClick={() => setIsSidebarOpen(true)} />
                      <Sidebar isOpen={isSidebarOpen} onClose={() => setIsSidebarOpen(false)} />
                      <AboutUs />
                    </>
                  </ProtectedRoute>
                }
              />
              <Route
                path="/contact-us"
                element={
                  <ProtectedRoute>
                    <>
                      <Header onMenuClick={() => setIsSidebarOpen(true)} />
                      <Sidebar isOpen={isSidebarOpen} onClose={() => setIsSidebarOpen(false)} />
                      <ContactUs />
                    </>
                  </ProtectedRoute>
                }
              />
              <Route path="/landing" element={<LandingPage />} />
              <Route path="/login" element={<LoginPage />} />
              <Route path="/register" element={<RegisterPage />} />
            </Routes>
          </Suspense>
        </div>
      </div>
    </HashRouter>
  );
}

export default App;