diff --git a/frontend/src/components/aura/VisitorCheckIn.tsx b/frontend/src/components/aura/VisitorCheckIn.tsx index 997a5ce..bbbb099 100644 --- a/frontend/src/components/aura/VisitorCheckIn.tsx +++ b/frontend/src/components/aura/VisitorCheckIn.tsx @@ -1,4 +1,4 @@ -import { useRef, useState } from "react"; +import { useRef, useState, ReactNode } from "react"; import { Link } from "react-router-dom"; import { CheckCircle, @@ -31,6 +31,93 @@ const commonStyles = { link: "font-medium text-cyan-600 hover:text-cyan-700 transition-colors hover:underline", }; +interface VisitorKioskShellProps { + children: ReactNode; + onBack?: () => void; + title?: ReactNode; + subtitle?: string; +} + +export const VisitorKioskShell = ({ children, onBack, title, subtitle }: VisitorKioskShellProps) => { + return ( +
+
+ {/* Left Hero Section - Fixed/Sticky on Desktop */} +
+ Modern Facility Hallway +
+ +
+ {onBack && ( + + )} + +
+ SECURE FACILITY +
+

+ Welcome to
+ + 777 Wolfpack + +

+

+ Please complete the check-in process to receive your digital visitor badge and safety clearance. +

+
    + {[ + "Digital NDA Signature", + "Safety Briefing", + "Instant Badge Issuance", + "Escort Assignment", + ].map((item, i) => ( +
  • + + {item} +
  • + ))} +
+
+
+ + {/* Right Content Section - Scrollable */} +
+ {onBack && ( + + )} + +
+ {(title || subtitle) && ( +
+ {title &&

{title}

} + {subtitle &&

{subtitle}

} +
+ )} + {children} +
+
+
+
+ ); +}; + interface VisitorCheckInProps { onBack: () => void; onSuccess: (data: { badgeNumber: string; visitId: string; message: string }) => void; @@ -153,297 +240,234 @@ const VisitorCheckIn = ({ onBack, onSuccess }: VisitorCheckInProps) => { }; return ( -
-
- {/* Left Hero Section - Fixed/Sticky on Desktop */} -
- Modern Facility Hallway + Visitor Check-In + + } + subtitle="Create your visitor profile for today." + > + {error && ( +
+ + {error} +
+ )} + + {/* Form */} +
+ {/* Name */} +
+ + setFormData({ ...formData, name: e.target.value })} + required + disabled={loading} /> -
+ +
- {/* Animated Particles/Orbs could go here for more 'Aura' */} + {/* Company */} +
+ + setFormData({ ...formData, company: e.target.value })} + disabled={loading} + /> + +
-
- - -
- SECURE FACILITY -
-

- Welcome to
- - 777 Wolfpack - -

-

- Please complete the check-in process to receive your digital visitor badge and safety clearance. -

-
    - {[ - "Digital NDA Signature", - "Safety Briefing", - "Instant Badge Issuance", - "Escort Assignment", - ].map((item, i) => ( -
  • - - {item} -
  • - ))} -
+
+ {/* Email */} +
+ + setFormData({ ...formData, email: e.target.value })} + disabled={loading} + /> + +
+ {/* Phone */} +
+ + setFormData({ ...formData, phone: e.target.value })} + disabled={loading} + /> +
- {/* Right Form Section - Scrollable */} -
-
+ + {/* Visitor Type Selector */} +
+ + setFormData({ ...formData, name: e.target.value })} - required - disabled={loading} - /> - -
- - {/* Company */} -
- - setFormData({ ...formData, company: e.target.value })} - disabled={loading} - /> - -
- -
- {/* Email */} -
- - setFormData({ ...formData, email: e.target.value })} - disabled={loading} - /> - -
- {/* Phone */} -
- - setFormData({ ...formData, phone: e.target.value })} - disabled={loading} - /> - -
-
- - {/* Purpose */} -
- - setFormData({ ...formData, purpose: e.target.value })} - required - disabled={loading} - /> - -
- - {/* Visitor Type Selector */} -
- - - -
- - {/* Photo Capture */} -
- {!showCamera && !capturedPhoto && ( - - )} - - {showCamera && ( -
-
- )} - - {capturedPhoto && ( -
- Captured -
- -
-
- - Photo Ready - -
-
- )} -
- - {/* NDA Checkbox */} - - - - -
+ + + + + + +
-
-
+ + {/* Photo Capture */} +
+ {!showCamera && !capturedPhoto && ( + + )} + + {showCamera && ( +
+
+ )} + + {capturedPhoto && ( +
+ Captured +
+ +
+
+ + Photo Ready + +
+
+ )} +
+ + {/* NDA Checkbox */} + + + + + ); }; diff --git a/frontend/src/pages/VisitorKioskPage.tsx b/frontend/src/pages/VisitorKioskPage.tsx index 8e1c944..efb4697 100644 --- a/frontend/src/pages/VisitorKioskPage.tsx +++ b/frontend/src/pages/VisitorKioskPage.tsx @@ -1,9 +1,8 @@ import { useState, useEffect } from 'react'; -import { Link } from 'react-router-dom'; import { QRCodeSVG as QRCode } from 'qrcode.react'; -import { User, Clock, CheckCircle, XCircle, UserPlus, LogOut, Search, Shield, AlertTriangle, Download, LayoutDashboard } from 'lucide-react'; +import { User, CheckCircle, XCircle, UserPlus, LogOut, Search, AlertTriangle } from 'lucide-react'; import { visitorsApi, Visitor, ActiveVisitor } from '../lib/visitorsApi'; -import VisitorCheckIn from '../components/aura/VisitorCheckIn'; +import VisitorCheckIn, { VisitorKioskShell } from '../components/aura/VisitorCheckIn'; type KioskMode = 'home' | 'new-visitor' | 'returning' | 'check-in' | 'check-out' | 'success'; @@ -11,7 +10,6 @@ export default function VisitorKioskPage() { const [mode, setMode] = useState('home'); const [activeVisitors, setActiveVisitors] = useState([]); const [searchResults, setSearchResults] = useState([]); - const [selectedVisitor, setSelectedVisitor] = useState(null); const [searchQuery, setSearchQuery] = useState(''); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); @@ -84,7 +82,6 @@ export default function VisitorKioskPage() { const resetToHome = () => { setMode('home'); - setSelectedVisitor(null); setSearchQuery(''); setSearchResults([]); setError(null); @@ -112,227 +109,193 @@ export default function VisitorKioskPage() { ); } + // Dynamic Title and Subtitle based on mode + let shellTitle = "Welcome"; + let shellSubtitle = "Please select an option to continue"; + + if (mode === 'returning') { + shellTitle = "Returning Visitor"; + shellSubtitle = "Quick check-in for registered visitors"; + } else if (mode === 'success') { + shellTitle = "Success"; + shellSubtitle = "Action completed successfully"; + } + return ( -
- {/* Header */} -
-
-
- + + {/* Error Alert */} + {error && ( +
+ + {error} + +
+ )} + + {/* Home Screen */} + {mode === 'home' && ( +
+
-
-
- - {new Date().toLocaleTimeString()} + + +
+ + + {/* Check Out Section */} + {activeVisitors.length > 0 && ( +
+

+ + Check Out ({activeVisitors.length} on-site) +

+
+ {activeVisitors.map(visitor => ( + + ))} +
+
+ )} +
+ )} + + {/* Returning Visitor Search */} + {mode === 'returning' && ( +
+
+
+ + setSearchQuery(e.target.value)} + onKeyDown={e => e.key === 'Enter' && handleSearch()} + className="w-full bg-slate-50 border border-slate-200 rounded-xl pl-12 pr-4 py-3 text-slate-900 text-lg focus:border-cyan-500 outline-none focus:ring-2 focus:ring-cyan-500/20 transition-all" + placeholder="Search by name..." + autoFocus + /> +
+
-
-
- {/* Main Content */} -
-
- - {/* Error Alert */} - {error && ( -
- - {error} - -
- )} - - {/* Home Screen */} - {mode === 'home' && ( -
-

Welcome

-

Please select an option to continue

- -
+ {searchResults.length > 0 && ( +
+ {searchResults.map(visitor => ( - - -
- - {/* Check Out Section */} - {activeVisitors.length > 0 && ( -
-

- - Check Out ({activeVisitors.length} visitors on-site) -

-
- {activeVisitors.map(visitor => ( - - ))} -
-
- )} -
- )} - - {/* Returning Visitor Search */} - {mode === 'returning' && ( -
- - -

Find Your Record

- -
-
- - setSearchQuery(e.target.value)} - onKeyDown={e => e.key === 'Enter' && handleSearch()} - className="w-full bg-slate-800 border border-slate-700 rounded-xl pl-12 pr-4 py-3 text-white text-lg focus:border-emerald-500 outline-none" - placeholder="Search by name, email, or company..." - /> -
- -
- - {searchResults.length > 0 && ( -
- {searchResults.map(visitor => ( - - ))} -
- )} - - {searchQuery && searchResults.length === 0 && !loading && ( -
- No visitors found. Try a different search or register as a new visitor. -
- )} -
- )} - - {/* Success Screen */} - {mode === 'success' && successData && ( -
-
- -
-

{successData.message}

- - {successData.badgeNumber && ( // Only show QR for Check-IN, not Check-OUT -
-
- -
-
-

Scan for Digital Badge

-

Use your phone to carry your badge with you.

+
{visitor.name}
+
+ {visitor.company && `${visitor.company} • `} + {visitor.type} +
- -
-

Badge Number

-

{successData.badgeNumber}

-
- -
- -
-
- )} - - {!successData.badgeNumber && ( // Auto-redirect for Check-OUT only -

Returning to home in 5 seconds...

- )} + + + ))}
)} + {searchQuery && searchResults.length === 0 && !loading && ( +
+ No visitors found.
Try a different search or register as new. +
+ )}
-
+ )} - {/* Footer */} - -
+ {/* Success Screen */} + {mode === 'success' && successData && ( +
+
+ +
+

{successData.message}

+ + {successData.badgeNumber && ( // Only show QR for Check-IN, not Check-OUT +
+
+ +
+ +
+

Scan for Digital Badge

+

Use your phone to carry your badge with you.

+
+ +
+

Badge Number

+

{successData.badgeNumber}

+
+ +
+ +
+
+ )} + + {!successData.badgeNumber && ( // Auto-redirect for Check-OUT only +

Returning to home in 5 seconds...

+ )} +
+ )} + ); }