Remote generation fixed
This commit is contained in:
BIN
backend/.DS_Store
vendored
BIN
backend/.DS_Store
vendored
Binary file not shown.
@@ -73,7 +73,7 @@ public class SecurityConfig {
|
||||
.requestMatchers(HttpMethod.GET, "/api/orders/user/**").authenticated()
|
||||
.requestMatchers(HttpMethod.GET, "/api/wallet/balance/**").authenticated()
|
||||
.requestMatchers(HttpMethod.GET, "/api/wallet/transactions/**").authenticated()
|
||||
.requestMatchers(HttpMethod.POST, "/api/wallet/topup").authenticated()
|
||||
.requestMatchers(HttpMethod.POST, "/api/wallet/topup").hasAnyRole("MASTER", "MANAGER", "STAFF")
|
||||
.requestMatchers(HttpMethod.POST, "/api/coupons/redeem").authenticated()
|
||||
.requestMatchers(HttpMethod.POST, "/api/feedback/**").authenticated()
|
||||
.requestMatchers(HttpMethod.GET, "/api/feedback/**").authenticated()
|
||||
|
||||
@@ -20,14 +20,14 @@ spring.jpa.properties.hibernate.jdbc.time_zone=Asia/Kolkata
|
||||
# JWT — REQUIRED environment variables
|
||||
# MUST provide a secure random key (min 256-bit)
|
||||
# ============================================================
|
||||
app.jwt.secret=${JWT_SECRET:dev_mode_insecure_secret_key_32_chars_long}
|
||||
app.jwt.secret=${JWT_SECRET}
|
||||
app.jwt.expiration-ms=86400000
|
||||
|
||||
# ============================================================
|
||||
# Master Account — REQUIRED environment variables
|
||||
# ============================================================
|
||||
app.master.username=${MASTER_USER:admin}
|
||||
app.master.password=${MASTER_PASSWORD:admin123}
|
||||
app.master.password=${MASTER_PASSWORD}
|
||||
|
||||
# File upload configuration
|
||||
spring.servlet.multipart.max-file-size=10MB
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 157 KiB After Width: | Height: | Size: 17 KiB |
@@ -35,14 +35,14 @@ const Layout = () => {
|
||||
return (
|
||||
<div className="min-h-screen bg-[#f8fafc] flex font-inter overflow-hidden h-screen">
|
||||
{/* Side Navigation Bar */}
|
||||
<aside className="w-64 bg-[#231651] text-white flex flex-col shadow-2xl z-50">
|
||||
<aside className="w-64 bg-[#001828] text-white flex flex-col shadow-2xl z-50">
|
||||
<div className="p-8">
|
||||
<div className="flex flex-col gap-6">
|
||||
<div className="bg-white rounded-2xl p-4 flex items-center justify-center border border-white/20 shadow-xl overflow-hidden">
|
||||
<div className="flex flex-col items-center justify-center text-center gap-4">
|
||||
<div className="bg-white rounded-2xl p-4 flex items-center justify-center border border-white/20 shadow-xl overflow-hidden w-full max-w-[180px]">
|
||||
<img src={CollegeLogo} alt="Logo" className="h-12 w-auto object-contain" />
|
||||
</div>
|
||||
<div>
|
||||
<span className="text-xl font-black tracking-tighter text-white">RIT COUNTER</span>
|
||||
<span className="text-xl font-black tracking-tighter text-white">TILLO COUNTER</span>
|
||||
<p className="text-[10px] font-bold text-white/40 uppercase tracking-widest mt-1">Institutional POS</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
@import "tailwindcss";
|
||||
|
||||
@theme {
|
||||
--color-primary: #231651;
|
||||
--color-secondary: #64748b;
|
||||
--color-background: #f8fafc;
|
||||
--color-primary: #08a850;
|
||||
--color-secondary: #001828;
|
||||
--color-background: #f4fbf7;
|
||||
--font-inter: "Inter", sans-serif;
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ const Login = () => {
|
||||
{/* Footer */}
|
||||
<div className="mt-auto text-center">
|
||||
<p className="text-[10px] font-black text-[#cbd5e1] uppercase tracking-[0.2em]">
|
||||
© 2026 RITCHENNAI • COUNTER SYSTEM
|
||||
© 2026 TILLO • COUNTER SYSTEM
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -149,7 +149,7 @@ const Login = () => {
|
||||
<div className="w-full h-full overflow-hidden shadow-2xl border-[12px] border-white bg-white">
|
||||
<img
|
||||
src={RitChennaiLogo}
|
||||
alt="RIT Chennai Building"
|
||||
alt="Tillo Building"
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-gradient-to-tr from-primary/20 to-transparent"></div>
|
||||
|
||||
@@ -7,7 +7,7 @@ export default {
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
primary: "#231651",
|
||||
primary: "#001828",
|
||||
secondary: "#64748b",
|
||||
background: "#f8fafc",
|
||||
},
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>RIT Canteen Dashboard</title>
|
||||
<title>Tillo Canteen Dashboard</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 157 KiB After Width: | Height: | Size: 17 KiB |
@@ -55,7 +55,7 @@ const AddTerminalModal: React.FC<AddTerminalModalProps> = ({ isOpen, onClose, on
|
||||
className="bg-white rounded-3xl shadow-2xl w-full max-w-md overflow-hidden relative"
|
||||
>
|
||||
<div className="p-6 border-b border-gray-100 flex items-center justify-between">
|
||||
<h3 className="text-xl font-bold text-[#231651]">Register New Terminal</h3>
|
||||
<h3 className="text-xl font-bold text-[#001828]">Register New Terminal</h3>
|
||||
<button onClick={onClose} className="p-2 hover:bg-gray-100 rounded-full transition-colors">
|
||||
<X size={20} className="text-gray-400" />
|
||||
</button>
|
||||
@@ -73,34 +73,34 @@ const AddTerminalModal: React.FC<AddTerminalModalProps> = ({ isOpen, onClose, on
|
||||
>
|
||||
<div className="space-y-2">
|
||||
<label className="text-sm font-semibold text-gray-700 flex items-center gap-2">
|
||||
<Monitor size={16} className="text-[#231651]" /> Terminal Name
|
||||
<Monitor size={16} className="text-[#001828]" /> Terminal Name
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
placeholder="e.g. Counter 1"
|
||||
className="w-full h-12 px-4 bg-gray-50 border border-gray-200 rounded-xl focus:ring-2 focus:ring-[#231651]/20 focus:border-[#231651] outline-none transition-all"
|
||||
className="w-full h-12 px-4 bg-gray-50 border border-gray-200 rounded-xl focus:ring-2 focus:ring-[#001828]/20 focus:border-[#001828] outline-none transition-all"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<label className="text-sm font-semibold text-gray-700 flex items-center gap-2">
|
||||
<MapPin size={16} className="text-[#231651]" /> Location
|
||||
<MapPin size={16} className="text-[#001828]" /> Location
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={location}
|
||||
onChange={(e) => setLocation(e.target.value)}
|
||||
placeholder="e.g. Main Entrance"
|
||||
className="w-full h-12 px-4 bg-gray-50 border border-gray-200 rounded-xl focus:ring-2 focus:ring-[#231651]/20 focus:border-[#231651] outline-none transition-all"
|
||||
className="w-full h-12 px-4 bg-gray-50 border border-gray-200 rounded-xl focus:ring-2 focus:ring-[#001828]/20 focus:border-[#001828] outline-none transition-all"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<button
|
||||
disabled={!name || !location}
|
||||
onClick={() => setStep(2)}
|
||||
className="w-full h-14 bg-[#231651] text-white rounded-2xl font-bold shadow-lg shadow-[#231651]/20 hover:scale-[1.02] active:scale-[0.98] transition-all disabled:opacity-50 disabled:scale-100"
|
||||
className="w-full h-14 bg-[#001828] text-white rounded-2xl font-bold shadow-lg shadow-[#001828]/20 hover:scale-[1.02] active:scale-[0.98] transition-all disabled:opacity-50 disabled:scale-100"
|
||||
>
|
||||
Set Security PIN
|
||||
</button>
|
||||
@@ -114,7 +114,7 @@ const AddTerminalModal: React.FC<AddTerminalModalProps> = ({ isOpen, onClose, on
|
||||
className="space-y-6"
|
||||
>
|
||||
<div className="text-center mb-4">
|
||||
<div className="inline-flex p-3 bg-purple-50 text-[#231651] rounded-2xl mb-3">
|
||||
<div className="inline-flex p-3 bg-purple-50 text-[#001828] rounded-2xl mb-3">
|
||||
<Lock size={24} />
|
||||
</div>
|
||||
<h4 className="text-lg font-bold text-gray-900">Create Security PIN</h4>
|
||||
@@ -133,7 +133,7 @@ const AddTerminalModal: React.FC<AddTerminalModalProps> = ({ isOpen, onClose, on
|
||||
<button
|
||||
disabled={pin.length < 4 || loading}
|
||||
onClick={handleSubmit}
|
||||
className="flex-[2] h-14 bg-[#231651] text-white rounded-2xl font-bold shadow-lg shadow-[#231651]/20 hover:scale-[1.02] active:scale-[0.98] transition-all disabled:opacity-50 disabled:scale-100"
|
||||
className="flex-[2] h-14 bg-[#001828] text-white rounded-2xl font-bold shadow-lg shadow-[#001828]/20 hover:scale-[1.02] active:scale-[0.98] transition-all disabled:opacity-50 disabled:scale-100"
|
||||
>
|
||||
{loading ? 'Registering...' : 'Register Terminal'}
|
||||
</button>
|
||||
|
||||
@@ -75,7 +75,7 @@ const LinkDeviceModal: React.FC<LinkDeviceModalProps> = ({
|
||||
className="bg-white rounded-3xl shadow-2xl w-full max-w-md overflow-hidden relative"
|
||||
>
|
||||
<div className="p-6 border-b border-gray-100 flex items-center justify-between">
|
||||
<h3 className="text-xl font-bold text-[#231651]">Link Physical Device</h3>
|
||||
<h3 className="text-xl font-bold text-[#001828]">Link Physical Device</h3>
|
||||
<button onClick={handleClose} className="p-2 hover:bg-gray-100 rounded-full transition-colors">
|
||||
<X size={20} className="text-gray-400" />
|
||||
</button>
|
||||
@@ -104,15 +104,15 @@ const LinkDeviceModal: React.FC<LinkDeviceModalProps> = ({
|
||||
{/* Step-by-step instructions */}
|
||||
<div className="p-4 bg-gray-50 rounded-2xl text-left space-y-2">
|
||||
<div className="flex items-start gap-3">
|
||||
<span className="flex-shrink-0 w-5 h-5 rounded-full bg-[#231651] text-white text-[10px] font-bold flex items-center justify-center mt-0.5">1</span>
|
||||
<span className="flex-shrink-0 w-5 h-5 rounded-full bg-[#001828] text-white text-[10px] font-bold flex items-center justify-center mt-0.5">1</span>
|
||||
<p className="text-xs text-gray-600 leading-relaxed">Power on the ESP32 device and connect it to Wi-Fi</p>
|
||||
</div>
|
||||
<div className="flex items-start gap-3">
|
||||
<span className="flex-shrink-0 w-5 h-5 rounded-full bg-[#231651] text-white text-[10px] font-bold flex items-center justify-center mt-0.5">2</span>
|
||||
<span className="flex-shrink-0 w-5 h-5 rounded-full bg-[#001828] text-white text-[10px] font-bold flex items-center justify-center mt-0.5">2</span>
|
||||
<p className="text-xs text-gray-600 leading-relaxed">A 6-digit OTP will appear on the device display</p>
|
||||
</div>
|
||||
<div className="flex items-start gap-3">
|
||||
<span className="flex-shrink-0 w-5 h-5 rounded-full bg-[#231651] text-white text-[10px] font-bold flex items-center justify-center mt-0.5">3</span>
|
||||
<span className="flex-shrink-0 w-5 h-5 rounded-full bg-[#001828] text-white text-[10px] font-bold flex items-center justify-center mt-0.5">3</span>
|
||||
<p className="text-xs text-gray-600 leading-relaxed">Enter that OTP below to link the device</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -138,7 +138,7 @@ const LinkDeviceModal: React.FC<LinkDeviceModalProps> = ({
|
||||
<button
|
||||
disabled={otp.length < 6 || loading}
|
||||
onClick={() => handleLink()}
|
||||
className="w-full h-14 bg-[#231651] text-white rounded-2xl font-bold shadow-lg shadow-[#231651]/20 hover:scale-[1.02] active:scale-[0.98] transition-all disabled:opacity-50 disabled:scale-100"
|
||||
className="w-full h-14 bg-[#001828] text-white rounded-2xl font-bold shadow-lg shadow-[#001828]/20 hover:scale-[1.02] active:scale-[0.98] transition-all disabled:opacity-50 disabled:scale-100"
|
||||
>
|
||||
{loading ? 'Linking Device...' : 'Link Device'}
|
||||
</button>
|
||||
@@ -179,7 +179,7 @@ const LinkDeviceModal: React.FC<LinkDeviceModalProps> = ({
|
||||
|
||||
<button
|
||||
onClick={handleClose}
|
||||
className="w-full h-14 bg-[#231651] text-white rounded-2xl font-bold shadow-lg shadow-[#231651]/20 hover:scale-[1.02] active:scale-[0.98] transition-all"
|
||||
className="w-full h-14 bg-[#001828] text-white rounded-2xl font-bold shadow-lg shadow-[#001828]/20 hover:scale-[1.02] active:scale-[0.98] transition-all"
|
||||
>
|
||||
Done
|
||||
</button>
|
||||
|
||||
@@ -45,7 +45,7 @@ const Numpad: React.FC<NumpadProps> = ({ value, onChange, maxLength = 4 }) => {
|
||||
initial={false}
|
||||
animate={{
|
||||
scale: i < value.length ? 1.2 : 1,
|
||||
backgroundColor: i < value.length ? '#231651' : '#e2e8f0'
|
||||
backgroundColor: i < value.length ? '#001828' : '#e2e8f0'
|
||||
}}
|
||||
className="w-3 h-3 rounded-full"
|
||||
/>
|
||||
@@ -67,7 +67,7 @@ const Numpad: React.FC<NumpadProps> = ({ value, onChange, maxLength = 4 }) => {
|
||||
className={cn(
|
||||
"h-14 flex items-center justify-center rounded-xl text-lg font-bold transition-all",
|
||||
btn === 'C' ? "text-red-500 hover:text-red-600" :
|
||||
btn === 'DEL' ? "text-gray-500" : "text-[#231651]"
|
||||
btn === 'DEL' ? "text-gray-500" : "text-[#001828]"
|
||||
)}
|
||||
>
|
||||
{btn === 'DEL' ? <Delete size={20} /> : btn}
|
||||
|
||||
@@ -78,7 +78,7 @@ const PinVerificationModal: React.FC<PinVerificationModalProps> = ({
|
||||
className="bg-white rounded-3xl shadow-2xl w-full max-w-md overflow-hidden relative"
|
||||
>
|
||||
<div className="p-6 border-b border-gray-100 flex items-center justify-between">
|
||||
<h3 className="text-xl font-bold text-[#231651]">Security Authentication</h3>
|
||||
<h3 className="text-xl font-bold text-[#001828]">Security Authentication</h3>
|
||||
<button onClick={handleClose} className="p-2 hover:bg-gray-100 rounded-full transition-colors">
|
||||
<X size={20} className="text-gray-400" />
|
||||
</button>
|
||||
@@ -124,7 +124,7 @@ const PinVerificationModal: React.FC<PinVerificationModalProps> = ({
|
||||
<button
|
||||
disabled={pin.length < 4 || loading}
|
||||
onClick={() => handleVerify()}
|
||||
className="w-full h-14 bg-[#231651] text-white rounded-2xl font-bold shadow-lg shadow-[#231651]/20 hover:scale-[1.02] active:scale-[0.98] transition-all disabled:opacity-50 disabled:scale-100"
|
||||
className="w-full h-14 bg-[#001828] text-white rounded-2xl font-bold shadow-lg shadow-[#001828]/20 hover:scale-[1.02] active:scale-[0.98] transition-all disabled:opacity-50 disabled:scale-100"
|
||||
>
|
||||
{loading ? 'Verifying...' : 'Verify PIN'}
|
||||
</button>
|
||||
@@ -146,14 +146,14 @@ const PinVerificationModal: React.FC<PinVerificationModalProps> = ({
|
||||
</div>
|
||||
|
||||
<div className="relative group">
|
||||
<div className="absolute -inset-1 bg-gradient-to-r from-purple-600 to-[#231651] rounded-2xl blur opacity-20 group-hover:opacity-40 transition duration-1000"></div>
|
||||
<div className="relative p-5 bg-gray-50 border border-gray-200 rounded-2xl break-all font-mono text-sm text-[#231651] flex items-center justify-between gap-4">
|
||||
<div className="absolute -inset-1 bg-gradient-to-r from-purple-600 to-[#001828] rounded-2xl blur opacity-20 group-hover:opacity-40 transition duration-1000"></div>
|
||||
<div className="relative p-5 bg-gray-50 border border-gray-200 rounded-2xl break-all font-mono text-sm text-[#001828] flex items-center justify-between gap-4">
|
||||
<span className="text-left">{apiKey}</span>
|
||||
<button
|
||||
onClick={copyToClipboard}
|
||||
className="p-2 hover:bg-white rounded-lg transition-colors shadow-sm shrink-0"
|
||||
>
|
||||
{copied ? <CheckCircle2 size={18} className="text-green-600" /> : <Copy size={18} className="text-[#231651]" />}
|
||||
{copied ? <CheckCircle2 size={18} className="text-green-600" /> : <Copy size={18} className="text-[#001828]" />}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -167,7 +167,7 @@ const PinVerificationModal: React.FC<PinVerificationModalProps> = ({
|
||||
|
||||
<button
|
||||
onClick={handleClose}
|
||||
className="w-full h-14 bg-[#231651] text-white rounded-2xl font-bold shadow-lg shadow-[#231651]/20 hover:scale-[1.02] active:scale-[0.98] transition-all"
|
||||
className="w-full h-14 bg-[#001828] text-white rounded-2xl font-bold shadow-lg shadow-[#001828]/20 hover:scale-[1.02] active:scale-[0.98] transition-all"
|
||||
>
|
||||
Close Session
|
||||
</button>
|
||||
|
||||
@@ -187,7 +187,7 @@ const Sidebar = () => {
|
||||
// Check if a sub-menu should be open based on the current location
|
||||
React.useEffect(() => {
|
||||
const currentMenu = menuItems.find(item =>
|
||||
item.subMenu?.some(sub => location.pathname.startsWith(sub.path))
|
||||
item.subMenu?.some(sub => location.pathname.startsWith(sub.path || ''))
|
||||
);
|
||||
if (currentMenu && !openMenus.includes(currentMenu.title)) {
|
||||
setOpenMenus(prev => [...prev, currentMenu.title]);
|
||||
@@ -197,21 +197,20 @@ const Sidebar = () => {
|
||||
return (
|
||||
<div className="w-64 bg-white h-screen border-r border-[#e2e8f0] flex flex-col fixed left-0 top-0 z-50 shadow-sm overflow-hidden font-inter">
|
||||
{/* Branding Section */}
|
||||
<div className="px-5 pt-8 pb-4 flex items-center">
|
||||
<div className="px-5 pt-8 pb-4 flex justify-center items-center w-full">
|
||||
<img src={collegeLogo} alt="Branding" className="h-14 w-auto object-contain brightness-[1.05]" />
|
||||
</div>
|
||||
|
||||
{/* Premium Search Integration (Modern Dashboards usually have this) */}
|
||||
<div className="px-3 mb-4">
|
||||
<div className="relative flex items-center group">
|
||||
<div className="absolute left-3 flex items-center justify-center pointer-events-none">
|
||||
<Search size={16} className="text-[#64748b] group-focus-within:text-[#231651] transition-colors" />
|
||||
<Search size={16} className="text-[#64748b] group-focus-within:text-[#001828] transition-colors" />
|
||||
</div>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Search Menu..."
|
||||
title="Search for a specific module or page"
|
||||
className="w-full h-10 bg-gray-50 border border-[#e2e8f0] rounded-xl pl-10 pr-4 text-[13px] font-medium outline-none transition-all focus:bg-white focus:border-[#231651]/30 focus:shadow-sm placeholder:text-[#94a3b8] text-[#1e293b]"
|
||||
className="w-full h-10 bg-gray-50 border border-[#e2e8f0] rounded-xl pl-10 pr-4 text-[13px] font-medium outline-none transition-all focus:bg-white focus:border-[#001828]/30 focus:shadow-sm placeholder:text-[#94a3b8] text-[#1e293b]"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,17 +4,17 @@
|
||||
|
||||
@theme {
|
||||
--font-sans: "Inter", "system-ui", "-apple-system", "sans-serif";
|
||||
--color-primary: #231651;
|
||||
--color-primary-light: #35217a;
|
||||
--color-primary-glow: rgba(35, 22, 81, 0.1);
|
||||
--color-bg-main: #D6FFF6;
|
||||
--color-primary: #08a850;
|
||||
--color-primary-light: #0cb859;
|
||||
--color-primary-glow: rgba(8, 168, 80, 0.08);
|
||||
--color-bg-main: #f4fbf7;
|
||||
--color-bg-sidebar: #ffffff;
|
||||
--color-text-dark: #231651;
|
||||
--color-text-primary: #231651;
|
||||
--color-text-secondary: #4a3e7a;
|
||||
--color-text-muted: #7b71af;
|
||||
--color-border: rgba(35, 22, 81, 0.1);
|
||||
--color-border-light: rgba(35, 22, 81, 0.05);
|
||||
--color-text-dark: #001828;
|
||||
--color-text-primary: #0f172a;
|
||||
--color-text-secondary: #475569;
|
||||
--color-text-muted: #94a3b8;
|
||||
--color-border: rgba(0, 24, 40, 0.08);
|
||||
--color-border-light: rgba(0, 24, 40, 0.04);
|
||||
}
|
||||
|
||||
@layer base {
|
||||
|
||||
@@ -170,7 +170,7 @@ const BaseMenu = () => {
|
||||
setNewItem({ name: '', description: '', active: true });
|
||||
setShowModal(true);
|
||||
}}
|
||||
className="bg-[#231651] text-white px-4 py-2 rounded-xl flex items-center gap-2 shadow-lg shadow-[#231651]/20 hover:scale-[1.02] active:scale-95 transition-all"
|
||||
className="bg-[#001828] text-white px-4 py-2 rounded-xl flex items-center gap-2 shadow-lg shadow-[#001828]/20 hover:scale-[1.02] active:scale-95 transition-all"
|
||||
>
|
||||
<Plus size={20} />
|
||||
<span>Add New Item</span>
|
||||
@@ -187,7 +187,7 @@ const BaseMenu = () => {
|
||||
placeholder="Search items..."
|
||||
value={searchTerm}
|
||||
onChange={(e) => setSearchTerm(e.target.value)}
|
||||
className="w-full pl-10 pr-4 py-2 bg-gray-50 border border-[#e2e8f0] rounded-lg text-sm focus:outline-none focus:border-[#231651]/30 transition-all"
|
||||
className="w-full pl-10 pr-4 py-2 bg-gray-50 border border-[#e2e8f0] rounded-lg text-sm focus:outline-none focus:border-[#001828]/30 transition-all"
|
||||
/>
|
||||
</div>
|
||||
<button className="flex items-center gap-2 px-3 py-2 border border-[#e2e8f0] rounded-lg text-sm text-[#64748b] hover:bg-gray-50 transition-all">
|
||||
@@ -242,7 +242,7 @@ const BaseMenu = () => {
|
||||
<td className="px-6 py-4 text-center">
|
||||
<button
|
||||
onClick={() => fetchAssociatedProducts(item)}
|
||||
className="p-2 text-[#231651] bg-[#231651]/5 hover:bg-[#231651]/10 rounded-xl transition-all"
|
||||
className="p-2 text-[#001828] bg-[#001828]/5 hover:bg-[#001828]/10 rounded-xl transition-all"
|
||||
title="View Associated Products"
|
||||
>
|
||||
<ShoppingCart size={18} />
|
||||
@@ -261,7 +261,7 @@ const BaseMenu = () => {
|
||||
<td className="px-6 py-4 text-right relative">
|
||||
<button
|
||||
onClick={() => setOpenMenuId(openMenuId === item.id ? null : item.id)}
|
||||
className="p-1.5 text-[#94a3b8] hover:text-[#231651] hover:bg-[#231651]/5 rounded-lg transition-all"
|
||||
className="p-1.5 text-[#94a3b8] hover:text-[#001828] hover:bg-[#001828]/5 rounded-lg transition-all"
|
||||
>
|
||||
<MoreVertical size={18} />
|
||||
</button>
|
||||
@@ -273,14 +273,14 @@ const BaseMenu = () => {
|
||||
>
|
||||
<button
|
||||
onClick={() => handleEdit(item)}
|
||||
className="w-full flex items-center gap-3 px-4 py-3 text-sm text-[#475569] hover:bg-gray-50 hover:text-[#231651] transition-all"
|
||||
className="w-full flex items-center gap-3 px-4 py-3 text-sm text-[#475569] hover:bg-gray-50 hover:text-[#001828] transition-all"
|
||||
>
|
||||
<Edit2 size={16} />
|
||||
<span className="font-semibold">Edit Item</span>
|
||||
</button>
|
||||
<button
|
||||
onClick={() => handleToggleActive(item)}
|
||||
className="w-full flex items-center gap-3 px-4 py-3 text-sm text-[#475569] hover:bg-gray-50 hover:text-[#231651] transition-all border-t border-[#e2e8f0]/50"
|
||||
className="w-full flex items-center gap-3 px-4 py-3 text-sm text-[#475569] hover:bg-gray-50 hover:text-[#001828] transition-all border-t border-[#e2e8f0]/50"
|
||||
>
|
||||
{item.active ? (
|
||||
<>
|
||||
@@ -346,9 +346,9 @@ const BaseMenu = () => {
|
||||
) : (
|
||||
<div className="space-y-3">
|
||||
{associatedProducts.map(product => (
|
||||
<div key={product.id} className="flex items-center justify-between p-4 bg-gray-50 rounded-2xl border border-[#e2e8f0] hover:border-[#231651]/20 transition-all group">
|
||||
<div key={product.id} className="flex items-center justify-between p-4 bg-gray-50 rounded-2xl border border-[#e2e8f0] hover:border-[#001828]/20 transition-all group">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="w-12 h-12 bg-white rounded-xl flex items-center justify-center text-[#231651] shadow-sm group-hover:scale-105 transition-transform">
|
||||
<div className="w-12 h-12 bg-white rounded-xl flex items-center justify-center text-[#001828] shadow-sm group-hover:scale-105 transition-transform">
|
||||
<Package size={24} />
|
||||
</div>
|
||||
<div>
|
||||
@@ -359,7 +359,7 @@ const BaseMenu = () => {
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-right">
|
||||
<p className="text-lg font-bold text-[#231651]">₹{product.price}</p>
|
||||
<p className="text-lg font-bold text-[#001828]">₹{product.price}</p>
|
||||
<p className="text-[10px] text-[#64748b] font-medium">Sale Price</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -371,7 +371,7 @@ const BaseMenu = () => {
|
||||
<div className="px-8 py-6 bg-gray-50/50 border-t border-[#e2e8f0] flex justify-end">
|
||||
<button
|
||||
onClick={() => setShowProductsModal(false)}
|
||||
className="px-6 py-2.5 bg-[#231651] text-white font-bold rounded-xl shadow-lg shadow-[#231651]/20 hover:scale-[1.02] active:scale-95 transition-all flex items-center gap-2"
|
||||
className="px-6 py-2.5 bg-[#001828] text-white font-bold rounded-xl shadow-lg shadow-[#001828]/20 hover:scale-[1.02] active:scale-95 transition-all flex items-center gap-2"
|
||||
>
|
||||
Close View
|
||||
</button>
|
||||
@@ -401,7 +401,7 @@ const BaseMenu = () => {
|
||||
value={newItem.name}
|
||||
onChange={(e) => setNewItem({ ...newItem, name: e.target.value })}
|
||||
placeholder="e.g. Fresh Tomato"
|
||||
className="w-full px-4 py-2.5 border border-[#e2e8f0] rounded-xl focus:outline-none focus:border-[#231651] focus:ring-1 focus:ring-[#231651] transition-all text-sm"
|
||||
className="w-full px-4 py-2.5 border border-[#e2e8f0] rounded-xl focus:outline-none focus:border-[#001828] focus:ring-1 focus:ring-[#001828] transition-all text-sm"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
@@ -411,14 +411,14 @@ const BaseMenu = () => {
|
||||
onChange={(e) => setNewItem({ ...newItem, description: e.target.value })}
|
||||
placeholder="Tell us more about this item..."
|
||||
rows={3}
|
||||
className="w-full px-4 py-2.5 border border-[#e2e8f0] rounded-xl focus:outline-none focus:border-[#231651] focus:ring-1 focus:ring-[#231651] transition-all text-sm resize-none"
|
||||
className="w-full px-4 py-2.5 border border-[#e2e8f0] rounded-xl focus:outline-none focus:border-[#001828] focus:ring-1 focus:ring-[#001828] transition-all text-sm resize-none"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center gap-3 py-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setNewItem({ ...newItem, active: !newItem.active })}
|
||||
className={`w-11 h-6 rounded-full transition-all relative ${newItem.active ? 'bg-[#231651]' : 'bg-gray-300'}`}
|
||||
className={`w-11 h-6 rounded-full transition-all relative ${newItem.active ? 'bg-[#001828]' : 'bg-gray-300'}`}
|
||||
>
|
||||
<div className={`absolute top-1 left-1 w-4 h-4 bg-white rounded-full transition-transform ${newItem.active ? 'translate-x-5' : ''}`} />
|
||||
</button>
|
||||
@@ -434,7 +434,7 @@ const BaseMenu = () => {
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
className="flex-1 px-4 py-2.5 bg-[#231651] text-white font-bold rounded-xl shadow-lg shadow-[#231651]/20 hover:scale-[1.02] active:scale-95 transition-all text-sm"
|
||||
className="flex-1 px-4 py-2.5 bg-[#001828] text-white font-bold rounded-xl shadow-lg shadow-[#001828]/20 hover:scale-[1.02] active:scale-95 transition-all text-sm"
|
||||
>
|
||||
{editingItem ? 'Update Item' : 'Save Item'}
|
||||
</button>
|
||||
|
||||
@@ -214,7 +214,7 @@ const Customers: React.FC = () => {
|
||||
{/* Header Section */}
|
||||
<div className="flex flex-col md:flex-row md:items-center justify-between gap-6 max-w-[1600px]">
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="w-14 h-14 bg-[#231651] rounded-xl flex items-center justify-center shadow-lg shadow-[#231651]/20">
|
||||
<div className="w-14 h-14 bg-[#001828] rounded-xl flex items-center justify-center shadow-lg shadow-[#001828]/20">
|
||||
<User className="text-white w-7 h-7" />
|
||||
</div>
|
||||
<div>
|
||||
@@ -225,25 +225,25 @@ const Customers: React.FC = () => {
|
||||
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="relative group min-w-[320px]">
|
||||
<Search className="absolute left-3 top-1/2 -translate-y-1/2 text-[#94a3b8] group-focus-within:text-[#231651] transition-colors" size={18} />
|
||||
<Search className="absolute left-3 top-1/2 -translate-y-1/2 text-[#94a3b8] group-focus-within:text-[#001828] transition-colors" size={18} />
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Search customers..."
|
||||
value={searchTerm}
|
||||
onChange={(e) => setSearchTerm(e.target.value)}
|
||||
className="w-full pl-10 pr-4 py-2 bg-white border border-[#e2e8f0] rounded-xl text-sm focus:outline-none focus:border-[#231651]/30 transition-all shadow-sm"
|
||||
className="w-full pl-10 pr-4 py-2 bg-white border border-[#e2e8f0] rounded-xl text-sm focus:outline-none focus:border-[#001828]/30 transition-all shadow-sm"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex p-1 bg-white border border-[#e2e8f0] rounded-xl shadow-sm">
|
||||
<button
|
||||
className={`p-1.5 rounded-lg transition-all ${viewMode === 'table' ? 'bg-[#231651] text-white' : 'text-[#64748b] hover:bg-gray-50'}`}
|
||||
className={`p-1.5 rounded-lg transition-all ${viewMode === 'table' ? 'bg-[#001828] text-white' : 'text-[#64748b] hover:bg-gray-50'}`}
|
||||
onClick={() => setViewMode('table')}
|
||||
>
|
||||
<List size={20} />
|
||||
</button>
|
||||
<button
|
||||
className={`p-1.5 rounded-lg transition-all ${viewMode === 'grid' ? 'bg-[#231651] text-white' : 'text-[#64748b] hover:bg-gray-50'}`}
|
||||
className={`p-1.5 rounded-lg transition-all ${viewMode === 'grid' ? 'bg-[#001828] text-white' : 'text-[#64748b] hover:bg-gray-50'}`}
|
||||
onClick={() => setViewMode('grid')}
|
||||
>
|
||||
<LayoutGrid size={20} />
|
||||
@@ -256,7 +256,7 @@ const Customers: React.FC = () => {
|
||||
<div className="max-w-[1600px]">
|
||||
{isLoading ? (
|
||||
<div className="flex flex-col items-center justify-center py-24 bg-white rounded-xl border border-[#e2e8f0] shadow-sm">
|
||||
<div className="w-10 h-10 border-4 border-[#231651]/10 border-t-[#231651] rounded-full animate-spin"></div>
|
||||
<div className="w-10 h-10 border-4 border-[#001828]/10 border-t-[#001828] rounded-full animate-spin"></div>
|
||||
<p className="mt-4 text-[#64748b] font-medium text-sm">Loading customer base...</p>
|
||||
</div>
|
||||
) : (
|
||||
@@ -280,7 +280,7 @@ const Customers: React.FC = () => {
|
||||
<tr key={user.id} className="hover:bg-gray-50/50 transition-all">
|
||||
<td className="px-6 py-4">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-10 h-10 bg-[#231651] rounded-lg flex items-center justify-center text-white font-bold text-sm">
|
||||
<div className="w-10 h-10 bg-[#001828] rounded-lg flex items-center justify-center text-white font-bold text-sm">
|
||||
{getInitials(user.name)}
|
||||
</div>
|
||||
<div>
|
||||
@@ -305,7 +305,7 @@ const Customers: React.FC = () => {
|
||||
<div className="w-8 h-8 bg-indigo-50 rounded-lg flex items-center justify-center text-indigo-600">
|
||||
<CircleDollarSign size={16} />
|
||||
</div>
|
||||
<span className="text-sm font-black text-[#231651]">
|
||||
<span className="text-sm font-black text-[#001828]">
|
||||
R{user.ritzTokenBalance?.toLocaleString() || '0'}
|
||||
</span>
|
||||
</div>
|
||||
@@ -323,7 +323,7 @@ const Customers: React.FC = () => {
|
||||
</span>
|
||||
</td>
|
||||
<td className="px-6 py-4 text-right relative">
|
||||
<button onClick={() => setOpenMenuId(openMenuId === user.id ? null : user.id)} className="p-1.5 text-[#94a3b8] hover:text-[#231651] rounded-lg transition-colors">
|
||||
<button onClick={() => setOpenMenuId(openMenuId === user.id ? null : user.id)} className="p-1.5 text-[#94a3b8] hover:text-[#001828] rounded-lg transition-colors">
|
||||
<MoreVertical size={18} />
|
||||
</button>
|
||||
|
||||
@@ -362,7 +362,7 @@ const Customers: React.FC = () => {
|
||||
{users.map(user => (
|
||||
<div key={user.id} className="group relative p-6 bg-white border border-[#e2e8f0] rounded-xl flex flex-col items-center text-center transition-all hover:shadow-lg hover:-translate-y-1">
|
||||
<div className="absolute top-4 right-4">
|
||||
<button onClick={() => setOpenMenuId(openMenuId === user.id ? null : user.id)} className="p-1.5 text-[#94a3b8] hover:text-[#231651] rounded-lg">
|
||||
<button onClick={() => setOpenMenuId(openMenuId === user.id ? null : user.id)} className="p-1.5 text-[#94a3b8] hover:text-[#001828] rounded-lg">
|
||||
<MoreVertical size={18} />
|
||||
</button>
|
||||
{openMenuId === user.id && (
|
||||
@@ -382,7 +382,7 @@ const Customers: React.FC = () => {
|
||||
</div>
|
||||
|
||||
<div className="relative mb-4">
|
||||
<div className="w-20 h-20 bg-[#231651] rounded-2xl flex items-center justify-center text-2xl font-bold text-white shadow-lg shadow-[#231651]/20">
|
||||
<div className="w-20 h-20 bg-[#001828] rounded-2xl flex items-center justify-center text-2xl font-bold text-white shadow-lg shadow-[#001828]/20">
|
||||
{getInitials(user.name)}
|
||||
</div>
|
||||
<div className={`absolute -bottom-1 -right-1 w-5 h-5 rounded-full border-4 border-white shadow-sm ${user.loggedIn ? 'bg-green-500' : 'bg-gray-400'}`}></div>
|
||||
@@ -405,7 +405,7 @@ const Customers: React.FC = () => {
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<button onClick={() => handleEditClick(user)} className="w-full py-2.5 bg-gray-50 border border-[#e2e8f0] text-[#1e293b] hover:bg-[#231651] hover:text-white rounded-xl flex items-center justify-center gap-2 text-sm font-bold transition-all">
|
||||
<button onClick={() => handleEditClick(user)} className="w-full py-2.5 bg-gray-50 border border-[#e2e8f0] text-[#1e293b] hover:bg-[#001828] hover:text-white rounded-xl flex items-center justify-center gap-2 text-sm font-bold transition-all">
|
||||
Edit Profile <Edit2 size={16} />
|
||||
</button>
|
||||
</div>
|
||||
@@ -430,11 +430,11 @@ const Customers: React.FC = () => {
|
||||
|
||||
{/* Edit User Modal - Positioned absolutely relative to viewport */}
|
||||
{showEditModal && (
|
||||
<div className="fixed inset-0 bg-[#231651]/20 backdrop-blur-sm z-[100] flex items-center justify-center p-4 overflow-y-auto">
|
||||
<div className="fixed inset-0 bg-[#001828]/20 backdrop-blur-sm z-[100] flex items-center justify-center p-4 overflow-y-auto">
|
||||
<div className="bg-white rounded-3xl w-full max-w-2xl shadow-2xl overflow-hidden animate-in zoom-in duration-300 my-auto">
|
||||
<div className="px-10 py-8 border-b border-[#e2e8f0] flex justify-between items-center bg-gray-50/50">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="w-12 h-12 bg-[#231651]/5 rounded-xl flex items-center justify-center text-[#231651]">
|
||||
<div className="w-12 h-12 bg-[#001828]/5 rounded-xl flex items-center justify-center text-[#001828]">
|
||||
<Edit2 size={24} />
|
||||
</div>
|
||||
<div>
|
||||
@@ -461,7 +461,7 @@ const Customers: React.FC = () => {
|
||||
setEditForm({...editForm, name: e.target.value});
|
||||
if (errors.name) setErrors({...errors, name: ''});
|
||||
}}
|
||||
className={`w-full pl-12 pr-4 py-4 bg-slate-50 border rounded-2xl text-base font-bold focus:ring-4 focus:ring-[#231651]/5 focus:border-[#231651] transition-all outline-none ${
|
||||
className={`w-full pl-12 pr-4 py-4 bg-slate-50 border rounded-2xl text-base font-bold focus:ring-4 focus:ring-[#001828]/5 focus:border-[#001828] transition-all outline-none ${
|
||||
errors.name ? 'border-red-500 ring-4 ring-red-500/5' : 'border-[#e2e8f0]'
|
||||
}`}
|
||||
placeholder="e.g. John Doe"
|
||||
@@ -484,7 +484,7 @@ const Customers: React.FC = () => {
|
||||
setEditForm({...editForm, mobileNumber: val});
|
||||
if (errors.mobileNumber) setErrors({...errors, mobileNumber: ''});
|
||||
}}
|
||||
className={`w-full pl-12 pr-4 py-4 bg-slate-50 border rounded-2xl text-base font-bold focus:ring-4 focus:ring-[#231651]/5 focus:border-[#231651] transition-all outline-none ${
|
||||
className={`w-full pl-12 pr-4 py-4 bg-slate-50 border rounded-2xl text-base font-bold focus:ring-4 focus:ring-[#001828]/5 focus:border-[#001828] transition-all outline-none ${
|
||||
errors.mobileNumber ? 'border-red-500 ring-4 ring-red-500/5' : 'border-[#e2e8f0]'
|
||||
}`}
|
||||
placeholder="10-digit number"
|
||||
@@ -507,7 +507,7 @@ const Customers: React.FC = () => {
|
||||
setEditForm({...editForm, pin: val});
|
||||
if (errors.pin) setErrors({...errors, pin: ''});
|
||||
}}
|
||||
className={`w-full pl-12 pr-12 py-4 bg-white border rounded-2xl text-base font-bold focus:ring-4 focus:ring-[#231651]/5 focus:border-[#231651] transition-all outline-none ${
|
||||
className={`w-full pl-12 pr-12 py-4 bg-white border rounded-2xl text-base font-bold focus:ring-4 focus:ring-[#001828]/5 focus:border-[#001828] transition-all outline-none ${
|
||||
errors.pin ? 'border-red-500 ring-4 ring-red-500/5' : 'border-[#e2e8f0]'
|
||||
}`}
|
||||
placeholder="Enter new 6-digit PIN"
|
||||
@@ -515,7 +515,7 @@ const Customers: React.FC = () => {
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setShowPin(!showPin)}
|
||||
className="absolute right-4 top-1/2 -translate-y-1/2 text-[#94a3b8] hover:text-[#231651] transition-colors p-1"
|
||||
className="absolute right-4 top-1/2 -translate-y-1/2 text-[#94a3b8] hover:text-[#001828] transition-colors p-1"
|
||||
>
|
||||
{showPin ? <EyeOff size={20} /> : <Eye size={20} />}
|
||||
</button>
|
||||
@@ -538,7 +538,7 @@ const Customers: React.FC = () => {
|
||||
<button
|
||||
type="submit"
|
||||
disabled={isSaving}
|
||||
className="flex-[1.5] px-8 py-4 bg-[#231651] text-white font-bold rounded-2xl shadow-xl shadow-[#231651]/20 hover:scale-[1.01] active:scale-95 transition-all flex items-center justify-center gap-3 text-sm"
|
||||
className="flex-[1.5] px-8 py-4 bg-[#001828] text-white font-bold rounded-2xl shadow-xl shadow-[#001828]/20 hover:scale-[1.01] active:scale-95 transition-all flex items-center justify-center gap-3 text-sm"
|
||||
>
|
||||
{isSaving ? (
|
||||
<><Loader2 size={20} className="animate-spin" /> Syncing Details...</>
|
||||
|
||||
@@ -91,7 +91,7 @@ const Login = () => {
|
||||
<h2 className="text-[10px] font-black tracking-[0.3em] text-[#1e293b] uppercase mb-2">
|
||||
Canteen Management System
|
||||
</h2>
|
||||
<div className="w-12 h-1 bg-[#231651] mx-auto rounded-full"></div>
|
||||
<div className="w-12 h-1 bg-[#001828] mx-auto rounded-full"></div>
|
||||
</div>
|
||||
|
||||
{/* Role Toggle */}
|
||||
@@ -107,7 +107,7 @@ const Login = () => {
|
||||
/>
|
||||
<button
|
||||
onClick={() => setRole('manager')}
|
||||
className={`flex-1 flex items-center justify-center gap-2 py-3 rounded-xl text-xs font-bold transition-all relative z-10 ${role === 'manager' ? 'text-[#231651]' : 'text-[#94a3b8] hover:text-[#64748b]'
|
||||
className={`flex-1 flex items-center justify-center gap-2 py-3 rounded-xl text-xs font-bold transition-all relative z-10 ${role === 'manager' ? 'text-[#001828]' : 'text-[#94a3b8] hover:text-[#64748b]'
|
||||
}`}
|
||||
>
|
||||
<UserCircle2 size={16} />
|
||||
@@ -115,7 +115,7 @@ const Login = () => {
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setRole('master')}
|
||||
className={`flex-1 flex items-center justify-center gap-2 py-3 rounded-xl text-xs font-bold transition-all relative z-10 ${role === 'master' ? 'text-[#231651]' : 'text-[#94a3b8] hover:text-[#64748b]'
|
||||
className={`flex-1 flex items-center justify-center gap-2 py-3 rounded-xl text-xs font-bold transition-all relative z-10 ${role === 'master' ? 'text-[#001828]' : 'text-[#94a3b8] hover:text-[#64748b]'
|
||||
}`}
|
||||
>
|
||||
<ShieldCheck size={16} />
|
||||
@@ -130,7 +130,7 @@ const Login = () => {
|
||||
Secure User ID
|
||||
</label>
|
||||
<div className="relative group">
|
||||
<div className="absolute inset-y-0 left-0 pl-4 flex items-center pointer-events-none text-[#94a3b8] group-focus-within:text-[#231651] transition-colors">
|
||||
<div className="absolute inset-y-0 left-0 pl-4 flex items-center pointer-events-none text-[#94a3b8] group-focus-within:text-[#001828] transition-colors">
|
||||
<User size={18} />
|
||||
</div>
|
||||
<input
|
||||
@@ -138,7 +138,7 @@ const Login = () => {
|
||||
value={username}
|
||||
onChange={(e) => setUsername(e.target.value)}
|
||||
placeholder="Username"
|
||||
className="w-full bg-white border-2 border-[#e2e8f0] focus:border-[#231651] rounded-2xl py-4 pl-12 pr-4 text-sm font-semibold outline-none transition-all placeholder:text-[#cbd5e1]"
|
||||
className="w-full bg-white border-2 border-[#e2e8f0] focus:border-[#001828] rounded-2xl py-4 pl-12 pr-4 text-sm font-semibold outline-none transition-all placeholder:text-[#cbd5e1]"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -148,12 +148,12 @@ const Login = () => {
|
||||
<label className="text-[10px] font-black text-[#94a3b8] uppercase tracking-widest">
|
||||
Passcode
|
||||
</label>
|
||||
<button type="button" className="text-[10px] font-black text-[#231651] uppercase hover:underline">
|
||||
<button type="button" className="text-[10px] font-black text-[#001828] uppercase hover:underline">
|
||||
Forgot Access?
|
||||
</button>
|
||||
</div>
|
||||
<div className="relative group">
|
||||
<div className="absolute inset-y-0 left-0 pl-4 flex items-center pointer-events-none text-[#94a3b8] group-focus-within:text-[#231651] transition-colors">
|
||||
<div className="absolute inset-y-0 left-0 pl-4 flex items-center pointer-events-none text-[#94a3b8] group-focus-within:text-[#001828] transition-colors">
|
||||
<Lock size={18} />
|
||||
</div>
|
||||
<input
|
||||
@@ -161,7 +161,7 @@ const Login = () => {
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
placeholder="••••••••"
|
||||
className="w-full bg-white border-2 border-[#e2e8f0] focus:border-[#231651] rounded-2xl py-4 pl-12 pr-12 text-sm font-semibold outline-none transition-all placeholder:text-[#cbd5e1]"
|
||||
className="w-full bg-white border-2 border-[#e2e8f0] focus:border-[#001828] rounded-2xl py-4 pl-12 pr-12 text-sm font-semibold outline-none transition-all placeholder:text-[#cbd5e1]"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
@@ -175,7 +175,7 @@ const Login = () => {
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
className="w-full bg-[#231651] text-white rounded-2xl py-4 font-black text-sm flex items-center justify-center gap-3 shadow-xl shadow-[#231651]/20 hover:scale-[1.02] active:scale-[0.98] transition-all overflow-hidden group relative"
|
||||
className="w-full bg-[#001828] text-white rounded-2xl py-4 font-black text-sm flex items-center justify-center gap-3 shadow-xl shadow-[#001828]/20 hover:scale-[1.02] active:scale-[0.98] transition-all overflow-hidden group relative"
|
||||
>
|
||||
<span className="relative z-10">CONNECT TO PORTAL</span>
|
||||
<ArrowRight size={18} className="relative z-10 group-hover:translate-x-1 transition-transform" />
|
||||
@@ -192,7 +192,7 @@ const Login = () => {
|
||||
{/* Footer */}
|
||||
<div className="mt-auto text-center">
|
||||
<p className="text-[10px] font-black text-[#cbd5e1] uppercase tracking-[0.2em]">
|
||||
© 2026 RITCHENNAI • SYSTEM PORTAL
|
||||
© 2026 TILLO • SYSTEM PORTAL
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -201,8 +201,8 @@ const Login = () => {
|
||||
<div className="hidden md:flex flex-1 relative bg-[#f8fafc] items-center justify-center p-8 overflow-hidden">
|
||||
|
||||
{/* Decorative Circles */}
|
||||
<div className="absolute top-20 right-20 w-64 h-64 bg-[#231651]/5 rounded-full blur-3xl"></div>
|
||||
<div className="absolute bottom-20 left-40 w-96 h-96 bg-[#231651]/5 rounded-full blur-3xl"></div>
|
||||
<div className="absolute top-20 right-20 w-64 h-64 bg-[#001828]/5 rounded-full blur-3xl"></div>
|
||||
<div className="absolute bottom-20 left-40 w-96 h-96 bg-[#001828]/5 rounded-full blur-3xl"></div>
|
||||
|
||||
{/* Image Container with Custom Shape (using clip-path or rounded corners) */}
|
||||
<motion.div
|
||||
@@ -214,11 +214,11 @@ const Login = () => {
|
||||
<div className="w-full h-full overflow-hidden shadow-2xl border-[12px] border-white bg-white">
|
||||
<img
|
||||
src={buildingPhoto}
|
||||
alt="RIT Chennai Building"
|
||||
alt="Tillo Building"
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
{/* Overlay Gradient */}
|
||||
<div className="absolute inset-0 bg-gradient-to-tr from-[#231651]/20 to-transparent"></div>
|
||||
<div className="absolute inset-0 bg-gradient-to-tr from-[#001828]/20 to-transparent"></div>
|
||||
</div>
|
||||
|
||||
</motion.div>
|
||||
|
||||
@@ -144,12 +144,12 @@ const Managers = () => {
|
||||
<div className="p-8 space-y-8 bg-[#f8fafc] min-h-screen font-inter">
|
||||
<div className="flex justify-between items-center">
|
||||
<div>
|
||||
<h1 className="text-3xl font-black text-[#231651]">Managers</h1>
|
||||
<h1 className="text-3xl font-black text-[#001828]">Managers</h1>
|
||||
<p className="text-[#64748b] text-sm mt-1">Manage portal access and role assignments</p>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => setIsModalOpen(true)}
|
||||
className="flex items-center gap-2 bg-[#231651] text-white px-6 py-3 rounded-2xl font-bold shadow-xl shadow-[#231651]/20 hover:scale-105 transition-all"
|
||||
className="flex items-center gap-2 bg-[#001828] text-white px-6 py-3 rounded-2xl font-bold shadow-xl shadow-[#001828]/20 hover:scale-105 transition-all"
|
||||
>
|
||||
<UserPlus size={20} />
|
||||
<span>Add New Member</span>
|
||||
@@ -160,20 +160,20 @@ const Managers = () => {
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
<div className="md:col-span-2 relative group flex items-center">
|
||||
<div className="absolute left-5 flex items-center justify-center pointer-events-none">
|
||||
<Search className="text-[#94a3b8] group-focus-within:text-[#231651] transition-colors" size={20} />
|
||||
<Search className="text-[#94a3b8] group-focus-within:text-[#001828] transition-colors" size={20} />
|
||||
</div>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Search by name or email..."
|
||||
value={searchQuery}
|
||||
onChange={(e) => setSearchQuery(e.target.value)}
|
||||
className="w-full h-14 bg-white border border-[#e2e8f0] rounded-2xl pl-14 pr-4 text-sm font-semibold outline-none transition-all focus:border-[#231651]/30 focus:shadow-md shadow-sm text-[#1e293b] placeholder:text-[#94a3b8]"
|
||||
className="w-full h-14 bg-white border border-[#e2e8f0] rounded-2xl pl-14 pr-4 text-sm font-semibold outline-none transition-all focus:border-[#001828]/30 focus:shadow-md shadow-sm text-[#1e293b] placeholder:text-[#94a3b8]"
|
||||
/>
|
||||
</div>
|
||||
<div className="bg-white p-4 rounded-2xl border border-[#e2e8f0] shadow-sm flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-[10px] font-black text-[#94a3b8] uppercase tracking-widest">Active Managers</p>
|
||||
<h3 className="text-2xl font-black text-[#231651]">{managers.length}</h3>
|
||||
<h3 className="text-2xl font-black text-[#001828]">{managers.length}</h3>
|
||||
</div>
|
||||
<div className="p-3 bg-emerald-50 text-emerald-600 rounded-xl">
|
||||
<Shield size={24} />
|
||||
@@ -202,7 +202,7 @@ const Managers = () => {
|
||||
<tr key={manager.id} className="hover:bg-gray-50/50 transition-colors">
|
||||
<td className="px-6 py-5">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-10 h-10 rounded-full bg-[#231651] text-white flex items-center justify-center font-bold">
|
||||
<div className="w-10 h-10 rounded-full bg-[#001828] text-white flex items-center justify-center font-bold">
|
||||
{manager.name.charAt(0)}
|
||||
</div>
|
||||
<div>
|
||||
@@ -265,7 +265,7 @@ const Managers = () => {
|
||||
<div className="p-8 md:p-10">
|
||||
<div className="flex justify-between items-start mb-8">
|
||||
<div>
|
||||
<h2 className="text-2xl font-black text-[#1e293b]">Create manager account for <span className="text-[#231651]">RIT Canteen</span></h2>
|
||||
<h2 className="text-2xl font-black text-[#1e293b]">Create manager account for <span className="text-[#001828]">Tillo Canteen</span></h2>
|
||||
</div>
|
||||
<button onClick={() => setIsModalOpen(false)} className="p-2 hover:bg-gray-100 rounded-full transition-colors text-[#94a3b8]">
|
||||
<X size={24} />
|
||||
@@ -283,7 +283,7 @@ const Managers = () => {
|
||||
value={formData.name}
|
||||
onChange={(e) => setFormData({...formData, name: e.target.value})}
|
||||
placeholder="e.g. Main Desk"
|
||||
className="w-full bg-white border-2 border-[#e2e8f0] focus:border-[#231651] rounded-2xl py-3 pl-4 pr-4 text-sm font-semibold outline-none transition-all"
|
||||
className="w-full bg-white border-2 border-[#e2e8f0] focus:border-[#001828] rounded-2xl py-3 pl-4 pr-4 text-sm font-semibold outline-none transition-all"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -298,8 +298,8 @@ const Managers = () => {
|
||||
type="email"
|
||||
value={formData.email}
|
||||
onChange={(e) => setFormData({...formData, email: e.target.value})}
|
||||
placeholder="manager@rit.edu"
|
||||
className="w-full bg-white border-2 border-[#e2e8f0] focus:border-[#231651] rounded-2xl py-3 pl-11 pr-4 text-sm font-semibold outline-none transition-all"
|
||||
placeholder="manager@tillo.com"
|
||||
className="w-full bg-white border-2 border-[#e2e8f0] focus:border-[#001828] rounded-2xl py-3 pl-11 pr-4 text-sm font-semibold outline-none transition-all"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -316,7 +316,7 @@ const Managers = () => {
|
||||
value={formData.password}
|
||||
onChange={(e) => setFormData({...formData, password: e.target.value})}
|
||||
placeholder="••••••••"
|
||||
className="w-full bg-white border-2 border-[#e2e8f0] focus:border-[#231651] rounded-2xl py-3 pl-11 pr-4 text-sm font-semibold outline-none transition-all"
|
||||
className="w-full bg-white border-2 border-[#e2e8f0] focus:border-[#001828] rounded-2xl py-3 pl-11 pr-4 text-sm font-semibold outline-none transition-all"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -326,7 +326,7 @@ const Managers = () => {
|
||||
onClick={() => setFormData({...formData, viewOnly: !formData.viewOnly})}
|
||||
className={cn(
|
||||
"w-5 h-5 rounded border-2 flex items-center justify-center cursor-pointer transition-all",
|
||||
formData.viewOnly ? "bg-[#231651] border-[#231651]" : "border-[#e2e8f0]"
|
||||
formData.viewOnly ? "bg-[#001828] border-[#001828]" : "border-[#e2e8f0]"
|
||||
)}
|
||||
>
|
||||
{formData.viewOnly && <Check size={14} className="text-white" />}
|
||||
@@ -345,8 +345,8 @@ const Managers = () => {
|
||||
className={cn(
|
||||
"flex flex-col items-center justify-center p-4 rounded-2xl border-2 cursor-pointer transition-all gap-2",
|
||||
formData.selectedSections.includes(section.id)
|
||||
? "bg-[#231651]/5 border-[#231651] text-[#231651]"
|
||||
: "bg-white border-[#e2e8f0] text-[#94a3b8] hover:border-[#231651]/30"
|
||||
? "bg-[#001828]/5 border-[#001828] text-[#001828]"
|
||||
: "bg-white border-[#e2e8f0] text-[#94a3b8] hover:border-[#001828]/30"
|
||||
)}
|
||||
>
|
||||
<section.icon size={20} />
|
||||
@@ -359,7 +359,7 @@ const Managers = () => {
|
||||
<div className="pt-4">
|
||||
<button
|
||||
type="submit"
|
||||
className="w-full bg-[#231651] text-white rounded-2xl py-4 font-black text-sm shadow-xl shadow-[#231651]/20 hover:scale-[1.02] active:scale-[0.98] transition-all"
|
||||
className="w-full bg-[#001828] text-white rounded-2xl py-4 font-black text-sm shadow-xl shadow-[#001828]/20 hover:scale-[1.02] active:scale-[0.98] transition-all"
|
||||
>
|
||||
Create Account
|
||||
</button>
|
||||
|
||||
@@ -164,7 +164,7 @@ const NewArrivals: React.FC = () => {
|
||||
<div className="p-8 font-inter bg-[#f8fafc] min-h-screen">
|
||||
<div className="flex justify-between items-center mb-10 max-w-[1400px] mx-auto">
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="w-14 h-14 bg-[#231651] rounded-2xl flex items-center justify-center shadow-2xl shadow-[#231651]/20">
|
||||
<div className="w-14 h-14 bg-[#001828] rounded-2xl flex items-center justify-center shadow-2xl shadow-[#001828]/20">
|
||||
<Rocket className="text-white w-7 h-7" />
|
||||
</div>
|
||||
<div>
|
||||
@@ -172,7 +172,7 @@ const NewArrivals: React.FC = () => {
|
||||
<p className="text-sm font-medium text-[#64748b]">Configure and publish incoming procurement stock to your live store</p>
|
||||
</div>
|
||||
</div>
|
||||
<button onClick={fetchDrafts} className="p-3 text-[#64748b] hover:bg-white hover:text-[#231651] rounded-2xl transition-all border border-transparent hover:border-[#e2e8f0] shadow-sm">
|
||||
<button onClick={fetchDrafts} className="p-3 text-[#64748b] hover:bg-white hover:text-[#001828] rounded-2xl transition-all border border-transparent hover:border-[#e2e8f0] shadow-sm">
|
||||
<RefreshCw size={22} className={loading ? 'animate-spin' : ''} />
|
||||
</button>
|
||||
</div>
|
||||
@@ -180,7 +180,7 @@ const NewArrivals: React.FC = () => {
|
||||
<div className="max-w-[1400px] mx-auto">
|
||||
{loading ? (
|
||||
<div className="flex flex-col items-center justify-center py-32 gap-4">
|
||||
<RefreshCw className="animate-spin text-[#231651]" size={40} />
|
||||
<RefreshCw className="animate-spin text-[#001828]" size={40} />
|
||||
<p className="text-[#64748b] font-bold uppercase tracking-widest text-xs">Fetching Drafts...</p>
|
||||
</div>
|
||||
) : drafts.length === 0 ? (
|
||||
@@ -194,7 +194,7 @@ const NewArrivals: React.FC = () => {
|
||||
) : (
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{drafts.map((draft) => (
|
||||
<div key={draft.id} className="group bg-white rounded-[2rem] border border-[#e2e8f0] shadow-sm hover:shadow-2xl hover:shadow-[#231651]/10 transition-all duration-500 overflow-hidden flex flex-col">
|
||||
<div key={draft.id} className="group bg-white rounded-[2rem] border border-[#e2e8f0] shadow-sm hover:shadow-2xl hover:shadow-[#001828]/10 transition-all duration-500 overflow-hidden flex flex-col">
|
||||
<div className="relative h-48 bg-gray-50 flex items-center justify-center overflow-hidden">
|
||||
{draft.imageData ? (
|
||||
<img src={draft.imageData} alt={draft.name} className="w-full h-full object-cover transition-transform duration-700 group-hover:scale-110" />
|
||||
@@ -205,7 +205,7 @@ const NewArrivals: React.FC = () => {
|
||||
</div>
|
||||
)}
|
||||
<div className="absolute top-4 left-4">
|
||||
<span className="px-3 py-1 bg-[#231651]/90 backdrop-blur-md text-white rounded-full text-[10px] font-black uppercase tracking-wider">Draft Arrival</span>
|
||||
<span className="px-3 py-1 bg-[#001828]/90 backdrop-blur-md text-white rounded-full text-[10px] font-black uppercase tracking-wider">Draft Arrival</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -219,7 +219,7 @@ const NewArrivals: React.FC = () => {
|
||||
<div className="mt-auto pt-6 border-t border-[#f1f5f9] flex items-center justify-between">
|
||||
<div className="flex flex-col">
|
||||
<span className="text-[10px] font-bold text-[#94a3b8] uppercase">Procurement Rate</span>
|
||||
<span className="text-base font-black text-[#231651]">₹{draft.basePrice || 0}</span>
|
||||
<span className="text-base font-black text-[#001828]">₹{draft.basePrice || 0}</span>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<button
|
||||
@@ -230,7 +230,7 @@ const NewArrivals: React.FC = () => {
|
||||
</button>
|
||||
<button
|
||||
onClick={() => handleEdit(draft)}
|
||||
className="px-5 py-2.5 bg-[#231651] text-white rounded-xl text-sm font-bold flex items-center gap-2 hover:bg-[#342475] transition-all shadow-lg shadow-[#231651]/20"
|
||||
className="px-5 py-2.5 bg-[#001828] text-white rounded-xl text-sm font-bold flex items-center gap-2 hover:bg-[#342475] transition-all shadow-lg shadow-[#001828]/20"
|
||||
>
|
||||
Edit & Publish <ArrowRight size={16} />
|
||||
</button>
|
||||
@@ -245,11 +245,11 @@ const NewArrivals: React.FC = () => {
|
||||
|
||||
{/* Draft Configuration Modal */}
|
||||
{showModal && formData && (
|
||||
<div className="fixed inset-0 bg-[#231651]/40 backdrop-blur-md z-[100] flex items-center justify-center p-4">
|
||||
<div className="fixed inset-0 bg-[#001828]/40 backdrop-blur-md z-[100] flex items-center justify-center p-4">
|
||||
<div className="bg-white rounded-[2.5rem] w-full max-w-5xl max-h-[90vh] shadow-2xl flex flex-col animate-in zoom-in duration-300">
|
||||
<div className="px-10 py-6 border-b border-[#e2e8f0] flex justify-between items-center bg-gray-50/50">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="p-2 bg-[#231651] text-white rounded-xl">
|
||||
<div className="p-2 bg-[#001828] text-white rounded-xl">
|
||||
<Edit2 size={24} />
|
||||
</div>
|
||||
<div>
|
||||
@@ -265,18 +265,18 @@ const NewArrivals: React.FC = () => {
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<label className="block text-[10px] uppercase font-black text-[#64748b] mb-2 tracking-widest ml-1">Product Name</label>
|
||||
<input required type="text" value={formData.name} onChange={(e) => setFormData({ ...formData, name: e.target.value })} className="w-full px-5 py-4 bg-white border-2 border-gray-50 focus:border-[#231651]/20 rounded-2xl text-sm font-bold outline-none transition-all" />
|
||||
<input required type="text" value={formData.name} onChange={(e) => setFormData({ ...formData, name: e.target.value })} className="w-full px-5 py-4 bg-white border-2 border-gray-50 focus:border-[#001828]/20 rounded-2xl text-sm font-bold outline-none transition-all" />
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-[10px] uppercase font-black text-[#64748b] mb-2 tracking-widest ml-1">Category</label>
|
||||
<select required value={formData.category} onChange={(e) => setFormData({ ...formData, category: e.target.value })} className="w-full px-5 py-4 bg-white border-2 border-gray-50 focus:border-[#231651]/20 rounded-2xl text-sm font-bold outline-none transition-all appearance-none cursor-pointer">
|
||||
<select required value={formData.category} onChange={(e) => setFormData({ ...formData, category: e.target.value })} className="w-full px-5 py-4 bg-white border-2 border-gray-50 focus:border-[#001828]/20 rounded-2xl text-sm font-bold outline-none transition-all appearance-none cursor-pointer">
|
||||
<option value="">Select Category</option>
|
||||
{baseItems.map(item => <option key={item.id} value={item.name}>{item.name}</option>)}
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-[10px] uppercase font-black text-[#64748b] mb-2 tracking-widest ml-1">Live Selling Price (R)</label>
|
||||
<input required type="number" value={formData.price} onChange={(e) => setFormData({ ...formData, price: parseFloat(e.target.value) || 0 })} className="w-full px-5 py-4 bg-[#231651]/5 border-2 border-transparent focus:border-[#231651]/20 rounded-2xl text-lg font-black text-[#231651] outline-none transition-all" />
|
||||
<input required type="number" value={formData.price} onChange={(e) => setFormData({ ...formData, price: parseFloat(e.target.value) || 0 })} className="w-full px-5 py-4 bg-[#001828]/5 border-2 border-transparent focus:border-[#001828]/20 rounded-2xl text-lg font-black text-[#001828] outline-none transition-all" />
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-[10px] uppercase font-black text-[#64748b] mb-2 tracking-widest ml-1">Stall Association</label>
|
||||
@@ -292,7 +292,7 @@ const NewArrivals: React.FC = () => {
|
||||
stalls: selectedStall ? [{ id: selectedStall.id, name: selectedStall.name }] : []
|
||||
});
|
||||
}}
|
||||
className="w-full px-5 py-4 bg-white border-2 border-gray-50 focus:border-[#231651]/20 rounded-2xl text-sm font-bold outline-none transition-all appearance-none cursor-pointer"
|
||||
className="w-full px-5 py-4 bg-white border-2 border-gray-50 focus:border-[#001828]/20 rounded-2xl text-sm font-bold outline-none transition-all appearance-none cursor-pointer"
|
||||
>
|
||||
<option value="">Choose Stall</option>
|
||||
{allStalls.map(stall => (
|
||||
@@ -315,7 +315,7 @@ const NewArrivals: React.FC = () => {
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-[10px] uppercase font-black text-[#64748b] mb-2 tracking-widest ml-1">Barcode</label>
|
||||
<input type="text" value={formData.barcode} onChange={(e) => setFormData({ ...formData, barcode: e.target.value })} className="w-full px-5 py-4 bg-white border-2 border-gray-50 focus:border-[#231651]/20 rounded-2xl text-sm font-bold outline-none" placeholder="Scan or type..." />
|
||||
<input type="text" value={formData.barcode} onChange={(e) => setFormData({ ...formData, barcode: e.target.value })} className="w-full px-5 py-4 bg-white border-2 border-gray-50 focus:border-[#001828]/20 rounded-2xl text-sm font-bold outline-none" placeholder="Scan or type..." />
|
||||
</div>
|
||||
<div className="p-6 bg-amber-50 rounded-2xl border border-amber-100 flex gap-4">
|
||||
<AlertCircle className="text-amber-500 flex-shrink-0" size={20} />
|
||||
@@ -331,7 +331,7 @@ const NewArrivals: React.FC = () => {
|
||||
<label className="block text-[10px] uppercase font-black text-[#64748b] mb-2 tracking-widest ml-1">Product Media</label>
|
||||
<div
|
||||
onClick={() => fileInputRef.current?.click()}
|
||||
className="border-2 border-dashed border-[#e2e8f0] rounded-3xl p-6 flex flex-col items-center justify-center text-[#94a3b8] hover:border-[#231651]/30 hover:bg-gray-50 transition-all cursor-pointer h-64 overflow-hidden shadow-inner bg-gray-50"
|
||||
className="border-2 border-dashed border-[#e2e8f0] rounded-3xl p-6 flex flex-col items-center justify-center text-[#94a3b8] hover:border-[#001828]/30 hover:bg-gray-50 transition-all cursor-pointer h-64 overflow-hidden shadow-inner bg-gray-50"
|
||||
>
|
||||
{formData.imageData ? (
|
||||
<img src={formData.imageData} alt="Preview" className="w-full h-full object-contain" />
|
||||
@@ -350,20 +350,20 @@ const NewArrivals: React.FC = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-12 flex gap-4 p-8 bg-[#231651]/5 rounded-[2rem] border border-[#231651]/10">
|
||||
<div className="mt-12 flex gap-4 p-8 bg-[#001828]/5 rounded-[2rem] border border-[#001828]/10">
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h3 className="text-sm font-black text-[#231651] uppercase tracking-wider">Availability Settings</h3>
|
||||
<button type="button" onClick={() => setFormData({ ...formData, sessionOptional: !formData.sessionOptional })} className={`w-12 h-6.5 rounded-full relative transition-all ${formData.sessionOptional ? 'bg-[#231651]' : 'bg-gray-300'}`}><div className={`absolute top-1 left-1 w-4.5 h-4.5 bg-white rounded-full transition-transform ${formData.sessionOptional ? 'translate-x-5.5' : ''}`} /></button>
|
||||
<h3 className="text-sm font-black text-[#001828] uppercase tracking-wider">Availability Settings</h3>
|
||||
<button type="button" onClick={() => setFormData({ ...formData, sessionOptional: !formData.sessionOptional })} className={`w-12 h-6.5 rounded-full relative transition-all ${formData.sessionOptional ? 'bg-[#001828]' : 'bg-gray-300'}`}><div className={`absolute top-1 left-1 w-4.5 h-4.5 bg-white rounded-full transition-transform ${formData.sessionOptional ? 'translate-x-5.5' : ''}`} /></button>
|
||||
</div>
|
||||
<p className="text-xs text-[#64748b] mb-4">Control which times of day this product is visible to customers.</p>
|
||||
{formData.sessionOptional && (
|
||||
<button type="button" onClick={() => setShowSessionModal(true)} className="flex items-center gap-2 px-6 py-3 bg-white border border-[#231651]/20 text-[#231651] text-xs font-black rounded-xl hover:bg-white shadow-sm transition-all"><Clock size={16} /> Advanced Session Configuration</button>
|
||||
<button type="button" onClick={() => setShowSessionModal(true)} className="flex items-center gap-2 px-6 py-3 bg-white border border-[#001828]/20 text-[#001828] text-xs font-black rounded-xl hover:bg-white shadow-sm transition-all"><Clock size={16} /> Advanced Session Configuration</button>
|
||||
)}
|
||||
</div>
|
||||
<div className="w-[1px] bg-[#231651]/10 mx-6"></div>
|
||||
<div className="w-[1px] bg-[#001828]/10 mx-6"></div>
|
||||
<div className="flex-1 flex flex-col justify-center">
|
||||
<button type="submit" disabled={isSaving} className="w-full py-5 bg-[#231651] text-white font-black rounded-2xl shadow-2xl shadow-[#231651]/30 hover:scale-[1.02] active:scale-[0.98] transition-all flex items-center justify-center gap-3 disabled:opacity-50">
|
||||
<button type="submit" disabled={isSaving} className="w-full py-5 bg-[#001828] text-white font-black rounded-2xl shadow-2xl shadow-[#001828]/30 hover:scale-[1.02] active:scale-[0.98] transition-all flex items-center justify-center gap-3 disabled:opacity-50">
|
||||
{isSaving ? <RefreshCw className="animate-spin" /> : <><Rocket size={22} /> Publish to Live Store</>}
|
||||
</button>
|
||||
</div>
|
||||
@@ -375,18 +375,18 @@ const NewArrivals: React.FC = () => {
|
||||
|
||||
{/* Session Modal (Reused from Products.tsx) */}
|
||||
{showSessionModal && formData && (
|
||||
<div className="fixed inset-0 bg-[#231651]/60 backdrop-blur-md z-[120] flex items-center justify-center p-4">
|
||||
<div className="fixed inset-0 bg-[#001828]/60 backdrop-blur-md z-[120] flex items-center justify-center p-4">
|
||||
<div className="bg-white rounded-[3rem] w-full max-w-4xl shadow-2xl overflow-hidden animate-in zoom-in duration-300">
|
||||
<div className="p-12">
|
||||
<h2 className="text-2xl font-black text-[#1e293b] text-center mb-10 tracking-tight">Weekly Availability Schedule</h2>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 max-h-[50vh] overflow-y-auto px-4 custom-scrollbar">
|
||||
{formData.sessions.map((session, index) => (
|
||||
<div key={session.dayOfWeek} className={`p-6 rounded-3xl border-2 transition-all ${session.active ? 'border-[#231651]/20 bg-[#231651]/5' : 'border-gray-100 bg-gray-50'}`}>
|
||||
<div key={session.dayOfWeek} className={`p-6 rounded-3xl border-2 transition-all ${session.active ? 'border-[#001828]/20 bg-[#001828]/5' : 'border-gray-100 bg-gray-50'}`}>
|
||||
<div className="flex items-center justify-between mb-6">
|
||||
<span className="text-lg font-black text-[#231651]">{session.dayOfWeek}</span>
|
||||
<span className="text-lg font-black text-[#001828]">{session.dayOfWeek}</span>
|
||||
<div
|
||||
onClick={() => updateSession(index, { active: !session.active })}
|
||||
className={`w-7 h-7 rounded-xl flex items-center justify-center cursor-pointer transition-all ${session.active ? 'bg-[#231651]' : 'border-2 border-gray-200 bg-white'}`}
|
||||
className={`w-7 h-7 rounded-xl flex items-center justify-center cursor-pointer transition-all ${session.active ? 'bg-[#001828]' : 'border-2 border-gray-200 bg-white'}`}
|
||||
>
|
||||
{session.active && <Check size={16} className="text-white" strokeWidth={4} />}
|
||||
</div>
|
||||
@@ -416,7 +416,7 @@ const NewArrivals: React.FC = () => {
|
||||
))}
|
||||
</div>
|
||||
<div className="flex justify-end gap-4 mt-12">
|
||||
<button onClick={() => setShowSessionModal(false)} className="px-12 py-4 bg-[#231651] text-white font-black rounded-2xl shadow-xl hover:scale-105 transition-all">Confirm Schedule</button>
|
||||
<button onClick={() => setShowSessionModal(false)} className="px-12 py-4 bg-[#001828] text-white font-black rounded-2xl shadow-xl hover:scale-105 transition-all">Confirm Schedule</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -486,7 +486,7 @@ const Orders: React.FC = () => {
|
||||
<div className="text-[10px] text-slate-400 font-medium">
|
||||
{format(new Date(order.createdAt), 'dd/MM/yy HH:mm')}
|
||||
</div>
|
||||
<div className="mt-3 text-[10px] inline-flex items-center gap-1 font-bold px-2 py-0.5 bg-[#231651] text-white rounded shadow-sm uppercase">
|
||||
<div className="mt-3 text-[10px] inline-flex items-center gap-1 font-bold px-2 py-0.5 bg-[#001828] text-white rounded shadow-sm uppercase">
|
||||
<User size={10} />
|
||||
{order.user?.name ? 'REGISTERED' : 'WALK-IN'}
|
||||
</div>
|
||||
@@ -643,7 +643,7 @@ const Orders: React.FC = () => {
|
||||
|
||||
{/* Bottom Summary Panel */}
|
||||
{/* Bottom Totals Summary - Re-engineered for Active Status */}
|
||||
<div className="bg-[#231651] p-8 text-white relative mt-8">
|
||||
<div className="bg-[#001828] p-8 text-white relative mt-8">
|
||||
{/* Decorative Pattern Background for Active Orders */}
|
||||
<div className="absolute inset-0 opacity-5 pointer-events-none bg-[radial-gradient(#fff_1px,transparent_1px)] [background-size:20px_20px]" />
|
||||
|
||||
@@ -875,7 +875,7 @@ const Orders: React.FC = () => {
|
||||
className={`w-full py-4 rounded-2xl text-xs font-black uppercase tracking-[0.2em] shadow-xl transition-all active:scale-[0.98] flex items-center justify-center gap-2 ${
|
||||
isUpdatingOrder || editingItems.length === 0
|
||||
? 'bg-slate-200 text-slate-400 cursor-not-allowed'
|
||||
: 'bg-[#231651] text-white hover:bg-[#2d1b66] shadow-indigo-100'
|
||||
: 'bg-[#001828] text-white hover:bg-[#2d1b66] shadow-indigo-100'
|
||||
}`}
|
||||
>
|
||||
{isUpdatingOrder ? <RefreshCw className="animate-spin" size={14} /> : <Check size={14} />}
|
||||
|
||||
@@ -307,7 +307,7 @@ const Products = () => {
|
||||
setFormData(emptyProduct);
|
||||
setShowModal(true);
|
||||
}}
|
||||
className="bg-[#231651] text-white px-4 py-2 rounded-xl flex items-center gap-2 shadow-lg shadow-[#231651]/20 hover:scale-[1.02] active:scale-95 transition-all"
|
||||
className="bg-[#001828] text-white px-4 py-2 rounded-xl flex items-center gap-2 shadow-lg shadow-[#001828]/20 hover:scale-[1.02] active:scale-95 transition-all"
|
||||
>
|
||||
<Plus size={20} />
|
||||
<span>Add New Product</span>
|
||||
@@ -324,7 +324,7 @@ const Products = () => {
|
||||
placeholder="Search products..."
|
||||
value={searchTerm}
|
||||
onChange={(e) => setSearchTerm(e.target.value)}
|
||||
className="w-full pl-10 pr-4 py-2 bg-gray-50 border border-[#e2e8f0] rounded-lg text-sm focus:outline-none focus:border-[#231651]/30 transition-all"
|
||||
className="w-full pl-10 pr-4 py-2 bg-gray-50 border border-[#e2e8f0] rounded-lg text-sm focus:outline-none focus:border-[#001828]/30 transition-all"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -359,7 +359,7 @@ const Products = () => {
|
||||
{product.imageData ? (
|
||||
<img src={product.imageData} alt={product.name} className="w-10 h-10 rounded-lg object-cover" />
|
||||
) : (
|
||||
<div className="w-10 h-10 rounded-lg bg-gray-100 flex items-center justify-center text-[#231651]"><Package size={20} /></div>
|
||||
<div className="w-10 h-10 rounded-lg bg-gray-100 flex items-center justify-center text-[#001828]"><Package size={20} /></div>
|
||||
)}
|
||||
<div>
|
||||
<p className="text-sm font-bold text-[#1e293b]">{product.name}</p>
|
||||
@@ -410,7 +410,7 @@ const Products = () => {
|
||||
</div>
|
||||
</td>
|
||||
<td className={`px-6 py-4 text-right relative ${openMenuId === product.id ? 'z-[100]' : 'z-0'}`}>
|
||||
<button onClick={() => setOpenMenuId(openMenuId === product.id ? null : (product.id as number))} className="p-1.5 text-[#94a3b8] hover:text-[#231651] rounded-lg transition-colors">
|
||||
<button onClick={() => setOpenMenuId(openMenuId === product.id ? null : (product.id as number))} className="p-1.5 text-[#94a3b8] hover:text-[#001828] rounded-lg transition-colors">
|
||||
<MoreVertical size={18} />
|
||||
</button>
|
||||
{openMenuId === product.id && (
|
||||
@@ -450,7 +450,7 @@ const Products = () => {
|
||||
|
||||
{/* Product Modal */}
|
||||
{showModal && (
|
||||
<div className="fixed inset-0 bg-[#231651]/20 backdrop-blur-sm z-[100] flex items-center justify-center p-4 overflow-y-auto">
|
||||
<div className="fixed inset-0 bg-[#001828]/20 backdrop-blur-sm z-[100] flex items-center justify-center p-4 overflow-y-auto">
|
||||
<div className="bg-white rounded-3xl w-full max-w-5xl shadow-2xl my-8 overflow-hidden">
|
||||
<div className="px-8 py-6 border-b border-[#e2e8f0] flex justify-between items-center bg-gray-50/50">
|
||||
<h2 className="text-xl font-bold text-[#1e293b]">{editingProduct ? 'Edit Product' : 'Add New Product'}</h2>
|
||||
@@ -495,7 +495,7 @@ const Products = () => {
|
||||
stalls: selectedStall ? [{ id: selectedStall.id, name: selectedStall.name }] : []
|
||||
});
|
||||
}}
|
||||
className="w-full px-4 py-3 border border-[#e2e8f0] rounded-xl text-sm font-semibold focus:ring-4 focus:ring-[#231651]/5 focus:border-[#231651] transition-all outline-none"
|
||||
className="w-full px-4 py-3 border border-[#e2e8f0] rounded-xl text-sm font-semibold focus:ring-4 focus:ring-[#001828]/5 focus:border-[#001828] transition-all outline-none"
|
||||
>
|
||||
<option value="">Select Stall</option>
|
||||
{allStalls.map(stall => (
|
||||
@@ -509,7 +509,7 @@ const Products = () => {
|
||||
<label className="block text-[11px] uppercase font-bold text-[#64748b] mb-1.5 ml-1">Product Image</label>
|
||||
<div
|
||||
onClick={() => fileInputRef.current?.click()}
|
||||
className="border-2 border-dashed border-[#e2e8f0] rounded-2xl p-6 flex flex-col items-center justify-center text-[#94a3b8] hover:border-[#231651]/30 hover:bg-gray-50 transition-all cursor-pointer h-40 overflow-hidden"
|
||||
className="border-2 border-dashed border-[#e2e8f0] rounded-2xl p-6 flex flex-col items-center justify-center text-[#94a3b8] hover:border-[#001828]/30 hover:bg-gray-50 transition-all cursor-pointer h-40 overflow-hidden"
|
||||
>
|
||||
{formData.imageData ? (
|
||||
<img src={formData.imageData} alt="Preview" className="w-full h-full object-contain" />
|
||||
@@ -531,12 +531,12 @@ const Products = () => {
|
||||
<div className="flex flex-col gap-4 min-w-[200px]">
|
||||
<div className="flex items-center justify-between gap-4">
|
||||
<div><p className="text-sm font-bold text-[#1e293b]">Additional Attributes</p></div>
|
||||
<button type="button" onClick={() => setFormData({ ...formData, attributesOptional: !formData.attributesOptional })} className={`w-11 h-6 rounded-full relative transition-all ${formData.attributesOptional ? 'bg-[#231651]' : 'bg-gray-300'}`}><div className={`absolute top-1 left-1 w-4 h-4 bg-white rounded-full transition-transform ${formData.attributesOptional ? 'translate-x-5' : ''}`} /></button>
|
||||
<button type="button" onClick={() => setFormData({ ...formData, attributesOptional: !formData.attributesOptional })} className={`w-11 h-6 rounded-full relative transition-all ${formData.attributesOptional ? 'bg-[#001828]' : 'bg-gray-300'}`}><div className={`absolute top-1 left-1 w-4 h-4 bg-white rounded-full transition-transform ${formData.attributesOptional ? 'translate-x-5' : ''}`} /></button>
|
||||
</div>
|
||||
{formData.attributesOptional && (
|
||||
<div className="flex gap-4 animate-in fade-in slide-in-from-left-2">
|
||||
<label className="flex items-center gap-2 cursor-pointer"><input type="checkbox" checked={formData.veg} onChange={(e) => setFormData({ ...formData, veg: e.target.checked })} className="w-4 h-4 rounded text-[#231651]" /><span className="text-xs font-semibold">Veg</span></label>
|
||||
<label className="flex items-center gap-2 cursor-pointer"><input type="checkbox" checked={formData.hasAllergy} onChange={(e) => setFormData({ ...formData, hasAllergy: e.target.checked })} className="w-4 h-4 rounded text-[#231651]" /><span className="text-xs font-semibold">Allergy</span></label>
|
||||
<label className="flex items-center gap-2 cursor-pointer"><input type="checkbox" checked={formData.veg} onChange={(e) => setFormData({ ...formData, veg: e.target.checked })} className="w-4 h-4 rounded text-[#001828]" /><span className="text-xs font-semibold">Veg</span></label>
|
||||
<label className="flex items-center gap-2 cursor-pointer"><input type="checkbox" checked={formData.hasAllergy} onChange={(e) => setFormData({ ...formData, hasAllergy: e.target.checked })} className="w-4 h-4 rounded text-[#001828]" /><span className="text-xs font-semibold">Allergy</span></label>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -544,10 +544,10 @@ const Products = () => {
|
||||
<div className="flex flex-col gap-4 min-w-[200px]">
|
||||
<div className="flex items-center justify-between gap-4">
|
||||
<div><p className="text-sm font-bold text-[#1e293b]">Session</p></div>
|
||||
<button type="button" onClick={() => setFormData({ ...formData, sessionOptional: !formData.sessionOptional })} className={`w-11 h-6 rounded-full relative transition-all ${formData.sessionOptional ? 'bg-[#231651]' : 'bg-gray-300'}`}><div className={`absolute top-1 left-1 w-4 h-4 bg-white rounded-full transition-transform ${formData.sessionOptional ? 'translate-x-5' : ''}`} /></button>
|
||||
<button type="button" onClick={() => setFormData({ ...formData, sessionOptional: !formData.sessionOptional })} className={`w-11 h-6 rounded-full relative transition-all ${formData.sessionOptional ? 'bg-[#001828]' : 'bg-gray-300'}`}><div className={`absolute top-1 left-1 w-4 h-4 bg-white rounded-full transition-transform ${formData.sessionOptional ? 'translate-x-5' : ''}`} /></button>
|
||||
</div>
|
||||
{formData.sessionOptional && (
|
||||
<button type="button" onClick={() => setShowSessionModal(true)} className="flex items-center gap-2 px-4 py-2 bg-white border border-[#231651]/20 text-[#231651] text-xs font-bold rounded-xl hover:bg-[#231651]/5 transition-all w-fit animate-in fade-in slide-in-from-left-2"><Clock size={14} /> Configure Session</button>
|
||||
<button type="button" onClick={() => setShowSessionModal(true)} className="flex items-center gap-2 px-4 py-2 bg-white border border-[#001828]/20 text-[#001828] text-xs font-bold rounded-xl hover:bg-[#001828]/5 transition-all w-fit animate-in fade-in slide-in-from-left-2"><Clock size={14} /> Configure Session</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
@@ -555,7 +555,7 @@ const Products = () => {
|
||||
|
||||
<div className="flex gap-4 mt-10">
|
||||
<button type="button" onClick={() => setShowModal(false)} className="flex-1 px-8 py-4 border-2 border-[#e2e8f0] text-[#64748b] font-bold rounded-2xl hover:bg-gray-50 transition-all">Discard</button>
|
||||
<button type="submit" className="flex-[2] px-8 py-4 bg-[#231651] text-white font-bold rounded-2xl shadow-xl hover:scale-[1.01] transition-all flex items-center justify-center gap-2"><Package size={20} /><span>{editingProduct ? 'Update Product' : 'Save Product'}</span></button>
|
||||
<button type="submit" className="flex-[2] px-8 py-4 bg-[#001828] text-white font-bold rounded-2xl shadow-xl hover:scale-[1.01] transition-all flex items-center justify-center gap-2"><Package size={20} /><span>{editingProduct ? 'Update Product' : 'Save Product'}</span></button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@@ -564,7 +564,7 @@ const Products = () => {
|
||||
|
||||
{/* Session Configuration Modal */}
|
||||
{showSessionModal && (
|
||||
<div className="fixed inset-0 bg-[#231651]/40 backdrop-blur-md z-[110] flex items-center justify-center p-4">
|
||||
<div className="fixed inset-0 bg-[#001828]/40 backdrop-blur-md z-[110] flex items-center justify-center p-4">
|
||||
<div className="bg-white rounded-[40px] w-full max-w-4xl shadow-2xl overflow-hidden animate-in zoom-in duration-300">
|
||||
<div className="p-10">
|
||||
<h2 className="text-2xl font-bold text-[#1e293b] text-center mb-8">Select the session that the time product show in menu</h2>
|
||||
|
||||
@@ -245,7 +245,7 @@ const Purchases: React.FC = () => {
|
||||
<div className="flex flex-col h-full bg-[#f8fafc] p-8 gap-8 font-inter overflow-y-auto">
|
||||
<div className="flex flex-col md:flex-row md:items-center justify-between gap-6 max-w-[1600px]">
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="w-14 h-14 bg-[#231651] rounded-xl flex items-center justify-center shadow-lg shadow-[#231651]/20">
|
||||
<div className="w-14 h-14 bg-[#001828] rounded-xl flex items-center justify-center shadow-lg shadow-[#001828]/20">
|
||||
<ShoppingCart className="text-white w-7 h-7" />
|
||||
</div>
|
||||
<div>
|
||||
@@ -258,7 +258,7 @@ const Purchases: React.FC = () => {
|
||||
<button
|
||||
onClick={() => setShowAddModal(true)}
|
||||
title="Create a new procurement order"
|
||||
className="px-5 py-2.5 bg-[#231651] text-white rounded-xl text-sm font-bold flex items-center gap-2 hover:scale-105 transition-all shadow-lg"
|
||||
className="px-5 py-2.5 bg-[#001828] text-white rounded-xl text-sm font-bold flex items-center gap-2 hover:scale-105 transition-all shadow-lg"
|
||||
>
|
||||
<Plus size={18} />
|
||||
Create Purchase
|
||||
@@ -269,7 +269,7 @@ const Purchases: React.FC = () => {
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Search purchases..."
|
||||
className="w-full pl-10 pr-4 py-2.5 bg-white border border-[#e2e8f0] rounded-xl text-sm focus:outline-none focus:border-[#231651]/30 transition-all shadow-sm"
|
||||
className="w-full pl-10 pr-4 py-2.5 bg-white border border-[#e2e8f0] rounded-xl text-sm focus:outline-none focus:border-[#001828]/30 transition-all shadow-sm"
|
||||
value={searchTerm}
|
||||
onChange={(e) => setSearchTerm(e.target.value)}
|
||||
/>
|
||||
@@ -300,7 +300,7 @@ const Purchases: React.FC = () => {
|
||||
</tr>
|
||||
) : orders.filter(o => (o.purchaseId || '').toLowerCase().includes((searchTerm || '').toLowerCase())).map((order) => (
|
||||
<tr key={order.id} className="hover:bg-gray-50/50 transition-all font-medium">
|
||||
<td className="px-6 py-4 text-sm font-bold text-[#231651]">{order.purchaseId}</td>
|
||||
<td className="px-6 py-4 text-sm font-bold text-[#001828]">{order.purchaseId}</td>
|
||||
<td className="px-6 py-4 text-sm text-[#64748b]">{new Date(order.date).toLocaleDateString()}</td>
|
||||
<td className="px-6 py-4">
|
||||
<div className="flex items-center gap-2">
|
||||
@@ -334,14 +334,14 @@ const Purchases: React.FC = () => {
|
||||
<button
|
||||
onClick={() => fetchOrderHistory(order)}
|
||||
title="View audit history of price changes"
|
||||
className="p-2 text-[#94a3b8] hover:text-[#231651] hover:bg-indigo-50 rounded-lg transition-all"
|
||||
className="p-2 text-[#94a3b8] hover:text-[#001828] hover:bg-indigo-50 rounded-lg transition-all"
|
||||
>
|
||||
<Eye size={18} />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => handleEditOrder(order)}
|
||||
title="Edit purchase order details"
|
||||
className="p-2 text-[#94a3b8] hover:text-[#231651] hover:bg-indigo-50 rounded-lg transition-all"
|
||||
className="p-2 text-[#94a3b8] hover:text-[#001828] hover:bg-indigo-50 rounded-lg transition-all"
|
||||
>
|
||||
<Edit2 size={18} />
|
||||
</button>
|
||||
@@ -362,11 +362,11 @@ const Purchases: React.FC = () => {
|
||||
</div>
|
||||
|
||||
{showAddModal && (
|
||||
<div className="fixed inset-0 bg-[#231651]/20 backdrop-blur-sm z-[100] flex items-center justify-center p-4">
|
||||
<div className="fixed inset-0 bg-[#001828]/20 backdrop-blur-sm z-[100] flex items-center justify-center p-4">
|
||||
<div className="bg-white rounded-3xl w-full max-w-5xl max-h-[90vh] shadow-2xl overflow-hidden flex flex-col animate-in zoom-in duration-300">
|
||||
<div className="px-8 py-6 border-b border-[#e2e8f0] flex justify-between items-center bg-gray-50/50">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="w-10 h-10 bg-[#231651] rounded-xl flex items-center justify-center text-white">
|
||||
<div className="w-10 h-10 bg-[#001828] rounded-xl flex items-center justify-center text-white">
|
||||
{editingOrder ? <ShoppingCart size={20} /> : <Plus size={20} />}
|
||||
</div>
|
||||
<div>
|
||||
@@ -383,11 +383,11 @@ const Purchases: React.FC = () => {
|
||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-6">
|
||||
<div>
|
||||
<label className="block text-[10px] uppercase font-black text-[#64748b] mb-1.5 tracking-widest ml-1">Purchase ID</label>
|
||||
<input type="text" value={newOrder.purchaseId} readOnly className="w-full px-4 py-3 bg-slate-50 border border-[#e2e8f0] rounded-xl text-sm font-bold text-[#231651] outline-none" />
|
||||
<input type="text" value={newOrder.purchaseId} readOnly className="w-full px-4 py-3 bg-slate-50 border border-[#e2e8f0] rounded-xl text-sm font-bold text-[#001828] outline-none" />
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-[10px] uppercase font-black text-[#64748b] mb-1.5 tracking-widest ml-1">Date</label>
|
||||
<input type="date" value={newOrder.date} onChange={e => setNewOrder({...newOrder, date: e.target.value})} className="w-full px-4 py-3 bg-white border border-[#e2e8f0] rounded-xl text-sm font-bold outline-none focus:border-[#231651]" />
|
||||
<input type="date" value={newOrder.date} onChange={e => setNewOrder({...newOrder, date: e.target.value})} className="w-full px-4 py-3 bg-white border border-[#e2e8f0] rounded-xl text-sm font-bold outline-none focus:border-[#001828]" />
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-[10px] uppercase font-black text-[#64748b] mb-1.5 tracking-widest ml-1">Vendor</label>
|
||||
@@ -395,7 +395,7 @@ const Purchases: React.FC = () => {
|
||||
required
|
||||
value={newOrder.vendorId}
|
||||
onChange={e => setNewOrder({...newOrder, vendorId: e.target.value})}
|
||||
className="w-full px-4 py-3 bg-white border border-[#e2e8f0] rounded-xl text-sm font-bold outline-none focus:border-[#231651]"
|
||||
className="w-full px-4 py-3 bg-white border border-[#e2e8f0] rounded-xl text-sm font-bold outline-none focus:border-[#001828]"
|
||||
>
|
||||
<option value="">Select Vendor</option>
|
||||
{vendors.map(v => <option key={v.id} value={v.id}>{v.name}</option>)}
|
||||
@@ -403,7 +403,7 @@ const Purchases: React.FC = () => {
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-[10px] uppercase font-black text-[#64748b] mb-1.5 tracking-widest ml-1">Status</label>
|
||||
<select value={newOrder.status} onChange={e => setNewOrder({...newOrder, status: e.target.value as any})} className="w-full px-4 py-3 bg-white border border-[#e2e8f0] rounded-xl text-sm font-bold outline-none focus:border-[#231651]">
|
||||
<select value={newOrder.status} onChange={e => setNewOrder({...newOrder, status: e.target.value as any})} className="w-full px-4 py-3 bg-white border border-[#e2e8f0] rounded-xl text-sm font-bold outline-none focus:border-[#001828]">
|
||||
<option value="OPEN">OPEN</option>
|
||||
<option value="TRANSIT">TRANSIT</option>
|
||||
<option value="BILLED">BILLED</option>
|
||||
@@ -418,7 +418,7 @@ const Purchases: React.FC = () => {
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<h3 className="text-sm font-black text-[#1e293b] uppercase tracking-wider">Order Items</h3>
|
||||
<button type="button" onClick={handleAddItem} className="text-xs font-bold text-[#231651] hover:underline flex items-center gap-1">
|
||||
<button type="button" onClick={handleAddItem} className="text-xs font-bold text-[#001828] hover:underline flex items-center gap-1">
|
||||
<Plus size={14} /> Add Item
|
||||
</button>
|
||||
</div>
|
||||
@@ -468,7 +468,7 @@ const Purchases: React.FC = () => {
|
||||
<span className="text-sm font-bold text-[#1e293b]">{p.name}</span>
|
||||
<div className="flex items-center gap-2 mt-0.5">
|
||||
<span className="text-[10px] bg-slate-100 text-slate-500 px-1.5 py-0.5 rounded uppercase font-black tracking-tighter">{p.category || 'No Category'}</span>
|
||||
<span className="text-[10px] font-bold text-[#231651]">Cost: ₹{p.basePrice || 0}</span>
|
||||
<span className="text-[10px] font-bold text-[#001828]">Cost: ₹{p.basePrice || 0}</span>
|
||||
</div>
|
||||
</button>
|
||||
))
|
||||
@@ -517,11 +517,11 @@ const Purchases: React.FC = () => {
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<label className="block text-[10px] uppercase font-black text-[#64748b] mb-1.5 tracking-widest ml-1">Reference ID</label>
|
||||
<input type="text" value={newOrder.referenceId} onChange={e => setNewOrder({...newOrder, referenceId: e.target.value})} className="w-full px-4 py-3 bg-white border border-[#e2e8f0] rounded-xl text-sm font-bold outline-none focus:border-[#231651]" placeholder="Optional ref #" />
|
||||
<input type="text" value={newOrder.referenceId} onChange={e => setNewOrder({...newOrder, referenceId: e.target.value})} className="w-full px-4 py-3 bg-white border border-[#e2e8f0] rounded-xl text-sm font-bold outline-none focus:border-[#001828]" placeholder="Optional ref #" />
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-[10px] uppercase font-black text-[#64748b] mb-1.5 tracking-widest ml-1">Instruction</label>
|
||||
<textarea rows={3} value={newOrder.instruction} onChange={e => setNewOrder({...newOrder, instruction: e.target.value})} className="w-full px-4 py-3 bg-white border border-[#e2e8f0] rounded-xl text-sm font-bold outline-none focus:border-[#231651]" placeholder="Any notes..." />
|
||||
<textarea rows={3} value={newOrder.instruction} onChange={e => setNewOrder({...newOrder, instruction: e.target.value})} className="w-full px-4 py-3 bg-white border border-[#e2e8f0] rounded-xl text-sm font-bold outline-none focus:border-[#001828]" placeholder="Any notes..." />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -540,14 +540,14 @@ const Purchases: React.FC = () => {
|
||||
<div className="h-[1px] bg-[#e2e8f0] my-2"></div>
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="font-black text-[#1e293b]">Net Amount</span>
|
||||
<span className="text-xl font-black text-[#231651]">₹{calculateTotal().toLocaleString()}</span>
|
||||
<span className="text-xl font-black text-[#001828]">₹{calculateTotal().toLocaleString()}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-4 pt-4">
|
||||
<button type="button" onClick={() => setShowAddModal(false)} className="px-10 py-4 border-2 border-[#e2e8f0] text-[#64748b] font-bold rounded-2xl hover:bg-gray-50 transition-all">Cancel</button>
|
||||
<button type="submit" disabled={isSaving} className="flex-1 px-10 py-4 bg-[#231651] text-white font-bold rounded-2xl shadow-xl shadow-[#231651]/20 hover:scale-[1.01] transition-all flex items-center justify-center gap-3">
|
||||
<button type="submit" disabled={isSaving} className="flex-1 px-10 py-4 bg-[#001828] text-white font-bold rounded-2xl shadow-xl shadow-[#001828]/20 hover:scale-[1.01] transition-all flex items-center justify-center gap-3">
|
||||
{isSaving ? <Loader2 className="animate-spin" /> : <><CheckCircle size={20} /> Finalize Purchase Order</>}
|
||||
</button>
|
||||
</div>
|
||||
@@ -556,9 +556,9 @@ const Purchases: React.FC = () => {
|
||||
</div>
|
||||
)}
|
||||
{showHistoryModal && activeHistoryOrder && (
|
||||
<div className="fixed inset-0 bg-[#231651]/20 backdrop-blur-sm z-[110] flex items-center justify-center p-4">
|
||||
<div className="fixed inset-0 bg-[#001828]/20 backdrop-blur-sm z-[110] flex items-center justify-center p-4">
|
||||
<div className="bg-white rounded-3xl w-full max-w-2xl shadow-2xl overflow-hidden animate-in zoom-in duration-300">
|
||||
<div className="px-8 py-6 border-b border-[#e2e8f0] flex justify-between items-center bg-[#231651] text-white">
|
||||
<div className="px-8 py-6 border-b border-[#e2e8f0] flex justify-between items-center bg-[#001828] text-white">
|
||||
<div className="flex items-center gap-4">
|
||||
<Eye size={20} />
|
||||
<div>
|
||||
@@ -589,7 +589,7 @@ const Purchases: React.FC = () => {
|
||||
</div>
|
||||
<div className="flex-1 pb-4">
|
||||
<div className="flex justify-between items-start mb-2">
|
||||
<span className="text-xs font-black text-[#231651] uppercase tracking-wider bg-slate-100 px-2 py-0.5 rounded">
|
||||
<span className="text-xs font-black text-[#001828] uppercase tracking-wider bg-slate-100 px-2 py-0.5 rounded">
|
||||
{new Date(h.changeDate).toLocaleString()}
|
||||
</span>
|
||||
<span className="text-[10px] font-bold text-[#94a3b8] italic">Amount Change</span>
|
||||
@@ -608,7 +608,7 @@ const Purchases: React.FC = () => {
|
||||
</div>
|
||||
|
||||
<div className="p-6 bg-slate-50 flex justify-end px-8">
|
||||
<button onClick={() => setShowHistoryModal(false)} className="px-6 py-2 bg-[#231651] text-white rounded-xl text-sm font-bold">Close Record</button>
|
||||
<button onClick={() => setShowHistoryModal(false)} className="px-6 py-2 bg-[#001828] text-white rounded-xl text-sm font-bold">Close Record</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -81,7 +81,7 @@ const RitzPage: React.FC = () => {
|
||||
return (
|
||||
<div className="p-8 bg-[#f8fafc] min-h-screen font-inter animate-slideUp">
|
||||
{/* Premium Header Banner */}
|
||||
<div className="relative overflow-hidden bg-[#231651] rounded-3xl p-8 mb-8 text-white shadow-2xl shadow-indigo-200">
|
||||
<div className="relative overflow-hidden bg-[#001828] rounded-3xl p-8 mb-8 text-white shadow-2xl shadow-indigo-200">
|
||||
<img
|
||||
src={colorVector}
|
||||
alt="Vector BG"
|
||||
@@ -149,7 +149,7 @@ const RitzPage: React.FC = () => {
|
||||
<button className="p-2.5 bg-slate-50 border border-slate-200 rounded-xl text-slate-600 hover:bg-slate-100 transition-colors">
|
||||
<Filter size={18} />
|
||||
</button>
|
||||
<button className="flex items-center gap-2 px-4 py-2.5 bg-[#231651] text-white rounded-xl font-bold text-sm shadow-lg shadow-indigo-100 hover:scale-[1.02] active:scale-95 transition-all">
|
||||
<button className="flex items-center gap-2 px-4 py-2.5 bg-[#001828] text-white rounded-xl font-bold text-sm shadow-lg shadow-indigo-100 hover:scale-[1.02] active:scale-95 transition-all">
|
||||
<Download size={18} /> Export
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -130,21 +130,21 @@ const Settings = () => {
|
||||
<div className="p-8 max-w-6xl mx-auto">
|
||||
<div className="mb-8 flex flex-col md:flex-row md:items-end md:justify-between gap-4">
|
||||
<div>
|
||||
<h1 className="text-3xl font-black text-[#231651] mb-2">Settings & Security</h1>
|
||||
<h1 className="text-3xl font-black text-[#001828] mb-2">Settings & Security</h1>
|
||||
<p className="text-[#64748b]">Manage your account and system access control</p>
|
||||
</div>
|
||||
|
||||
<div className="flex bg-gray-100 p-1.5 rounded-2xl w-fit">
|
||||
<button
|
||||
onClick={() => setActiveTab('profile')}
|
||||
className={`px-6 py-2.5 rounded-xl font-bold text-sm transition-all flex items-center gap-2 ${activeTab === 'profile' ? 'bg-white text-[#231651] shadow-sm' : 'text-[#64748b] hover:text-[#231651]'}`}
|
||||
className={`px-6 py-2.5 rounded-xl font-bold text-sm transition-all flex items-center gap-2 ${activeTab === 'profile' ? 'bg-white text-[#001828] shadow-sm' : 'text-[#64748b] hover:text-[#001828]'}`}
|
||||
>
|
||||
<User size={18} />
|
||||
My Account
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setActiveTab('team')}
|
||||
className={`px-6 py-2.5 rounded-xl font-bold text-sm transition-all flex items-center gap-2 ${activeTab === 'team' ? 'bg-white text-[#231651] shadow-sm' : 'text-[#64748b] hover:text-[#231651]'}`}
|
||||
className={`px-6 py-2.5 rounded-xl font-bold text-sm transition-all flex items-center gap-2 ${activeTab === 'team' ? 'bg-white text-[#001828] shadow-sm' : 'text-[#64748b] hover:text-[#001828]'}`}
|
||||
>
|
||||
<Users size={18} />
|
||||
Team Management
|
||||
@@ -164,7 +164,7 @@ const Settings = () => {
|
||||
{/* Left Card: Summary */}
|
||||
<div className="lg:col-span-1">
|
||||
<div className="bg-white rounded-3xl p-6 border border-[#e2e8f0] shadow-sm text-center">
|
||||
<div className="w-24 h-24 bg-gradient-to-br from-[#231651] to-[#6366f1] rounded-full mx-auto mb-4 flex items-center justify-center text-white shadow-xl shadow-indigo-100">
|
||||
<div className="w-24 h-24 bg-gradient-to-br from-[#001828] to-[#6366f1] rounded-full mx-auto mb-4 flex items-center justify-center text-white shadow-xl shadow-indigo-100">
|
||||
<User size={40} />
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-[#1e293b]">{currentUser?.name}</h3>
|
||||
@@ -268,7 +268,7 @@ const Settings = () => {
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
|
||||
<button type="submit" disabled={status === 'loading'} className="bg-[#231651] text-white px-8 py-3 rounded-xl font-bold flex items-center gap-2 hover:bg-opacity-90 transition-all disabled:opacity-50">
|
||||
<button type="submit" disabled={status === 'loading'} className="bg-[#001828] text-white px-8 py-3 rounded-xl font-bold flex items-center gap-2 hover:bg-opacity-90 transition-all disabled:opacity-50">
|
||||
<Save size={18} /> Save Profile
|
||||
</button>
|
||||
</div>
|
||||
@@ -286,12 +286,12 @@ const Settings = () => {
|
||||
>
|
||||
<div className="flex justify-between items-center bg-white p-6 rounded-3xl border border-[#e2e8f0] shadow-sm">
|
||||
<div>
|
||||
<h3 className="text-xl font-bold text-[#231651]">Administrator Team</h3>
|
||||
<h3 className="text-xl font-bold text-[#001828]">Administrator Team</h3>
|
||||
<p className="text-sm text-[#64748b]">Found {admins.length} active system administrators</p>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => setShowAddModal(true)}
|
||||
className="bg-gradient-to-r from-[#231651] to-[#6366f1] text-white px-6 py-3 rounded-xl font-bold flex items-center gap-2 shadow-lg shadow-indigo-100 hover:scale-[1.02] transition-all"
|
||||
className="bg-gradient-to-r from-[#001828] to-[#6366f1] text-white px-6 py-3 rounded-xl font-bold flex items-center gap-2 shadow-lg shadow-indigo-100 hover:scale-[1.02] transition-all"
|
||||
>
|
||||
<UserPlus size={18} />
|
||||
Add New Admin
|
||||
@@ -302,7 +302,7 @@ const Settings = () => {
|
||||
{admins.map((admin) => (
|
||||
<div key={admin.id} className="bg-white p-6 rounded-3xl border border-[#e2e8f0] shadow-sm hover:shadow-md transition-all group">
|
||||
<div className="flex items-start justify-between mb-4">
|
||||
<div className="w-12 h-12 bg-gray-100 rounded-2xl flex items-center justify-center text-[#231651] group-hover:bg-[#231651] group-hover:text-white transition-colors">
|
||||
<div className="w-12 h-12 bg-gray-100 rounded-2xl flex items-center justify-center text-[#001828] group-hover:bg-[#001828] group-hover:text-white transition-colors">
|
||||
<User size={24} />
|
||||
</div>
|
||||
{admin.id === currentUser?.id && (
|
||||
@@ -331,9 +331,9 @@ const Settings = () => {
|
||||
<AnimatePresence>
|
||||
{showAddModal && (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center p-4">
|
||||
<motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} onClick={() => setShowAddModal(false)} className="absolute inset-0 bg-[#231651]/20 backdrop-blur-sm" />
|
||||
<motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} onClick={() => setShowAddModal(false)} className="absolute inset-0 bg-[#001828]/20 backdrop-blur-sm" />
|
||||
<motion.div initial={{ scale: 0.9, opacity: 0 }} animate={{ scale: 1, opacity: 1 }} exit={{ scale: 0.9, opacity: 0 }} className="bg-white w-full max-w-md rounded-[32px] overflow-hidden shadow-2xl relative z-10">
|
||||
<div className="bg-[#231651] p-6 text-white text-center">
|
||||
<div className="bg-[#001828] p-6 text-white text-center">
|
||||
<div className="w-16 h-16 bg-white/10 rounded-2xl flex items-center justify-center mx-auto mb-4">
|
||||
<UserPlus size={32} />
|
||||
</div>
|
||||
@@ -384,7 +384,7 @@ const Settings = () => {
|
||||
|
||||
<div className="flex gap-3 pt-2">
|
||||
<button type="button" onClick={() => setShowAddModal(false)} className="flex-1 py-3 rounded-xl font-bold text-gray-500 hover:bg-gray-50 transition-all">Cancel</button>
|
||||
<button type="submit" disabled={status === 'loading'} className="flex-1 bg-[#231651] text-white py-3 rounded-xl font-bold flex items-center justify-center gap-2 hover:bg-indigo-700 transition-all disabled:opacity-50">
|
||||
<button type="submit" disabled={status === 'loading'} className="flex-1 bg-[#001828] text-white py-3 rounded-xl font-bold flex items-center justify-center gap-2 hover:bg-indigo-700 transition-all disabled:opacity-50">
|
||||
{status === 'loading' ? <div className="w-4 h-4 border-2 border-white/30 border-t-white rounded-full animate-spin" /> : <>Create User <ArrowRight size={16} /></>}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -107,12 +107,12 @@ const Staff = () => {
|
||||
<div className="p-8 space-y-8 bg-[#f8fafc] min-h-screen font-inter">
|
||||
<div className="flex justify-between items-center">
|
||||
<div>
|
||||
<h1 className="text-3xl font-black text-[#231651]">Staff Management</h1>
|
||||
<h1 className="text-3xl font-black text-[#001828]">Staff Management</h1>
|
||||
<p className="text-[#64748b] text-sm mt-1">Manage your team members and their portal permissions</p>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => setIsModalOpen(true)}
|
||||
className="flex items-center gap-2 bg-[#231651] text-white px-6 py-3 rounded-2xl font-bold shadow-xl shadow-[#231651]/20 hover:scale-105 transition-all"
|
||||
className="flex items-center gap-2 bg-[#001828] text-white px-6 py-3 rounded-2xl font-bold shadow-xl shadow-[#001828]/20 hover:scale-105 transition-all"
|
||||
>
|
||||
<UserPlus size={20} />
|
||||
<span>Add Staff Member</span>
|
||||
@@ -130,13 +130,13 @@ const Staff = () => {
|
||||
placeholder="Search by name or username..."
|
||||
value={searchQuery}
|
||||
onChange={(e) => setSearchQuery(e.target.value)}
|
||||
className="w-full h-14 bg-white border border-[#e2e8f0] rounded-2xl pl-14 pr-4 text-sm font-semibold outline-none transition-all focus:border-[#231651]/30 focus:shadow-md shadow-sm text-[#1e293b] placeholder:text-[#94a3b8]"
|
||||
className="w-full h-14 bg-white border border-[#e2e8f0] rounded-2xl pl-14 pr-4 text-sm font-semibold outline-none transition-all focus:border-[#001828]/30 focus:shadow-md shadow-sm text-[#1e293b] placeholder:text-[#94a3b8]"
|
||||
/>
|
||||
</div>
|
||||
<div className="bg-white p-4 rounded-2xl border border-[#e2e8f0] shadow-sm flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-[10px] font-black text-[#94a3b8] uppercase tracking-widest">Total Staff</p>
|
||||
<h3 className="text-2xl font-black text-[#231651]">{staffList.length}</h3>
|
||||
<h3 className="text-2xl font-black text-[#001828]">{staffList.length}</h3>
|
||||
</div>
|
||||
<div className="p-3 bg-indigo-50 text-indigo-600 rounded-xl">
|
||||
<Contact size={24} />
|
||||
@@ -164,7 +164,7 @@ const Staff = () => {
|
||||
<tr key={staff.id} className="hover:bg-gray-50/50 transition-colors">
|
||||
<td className="px-6 py-5">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-10 h-10 rounded-full bg-[#231651] text-white flex items-center justify-center font-bold">
|
||||
<div className="w-10 h-10 rounded-full bg-[#001828] text-white flex items-center justify-center font-bold">
|
||||
{staff.name.charAt(0)}
|
||||
</div>
|
||||
<div>
|
||||
@@ -215,7 +215,7 @@ const Staff = () => {
|
||||
<div className="p-8 md:p-10 max-h-[90vh] overflow-y-auto">
|
||||
<div className="flex justify-between items-start mb-8">
|
||||
<div>
|
||||
<h2 className="text-2xl font-black text-[#1e293b]">Add New <span className="text-[#231651]">Staff Member</span></h2>
|
||||
<h2 className="text-2xl font-black text-[#1e293b]">Add New <span className="text-[#001828]">Staff Member</span></h2>
|
||||
<p className="text-xs font-bold text-gray-400 mt-1">Configure account details and portal access</p>
|
||||
</div>
|
||||
<button onClick={() => setIsModalOpen(false)} className="p-2 hover:bg-gray-100 rounded-full transition-colors text-[#94a3b8]">
|
||||
@@ -233,7 +233,7 @@ const Staff = () => {
|
||||
value={formData.name}
|
||||
onChange={(e) => setFormData({...formData, name: e.target.value})}
|
||||
placeholder="John Doe"
|
||||
className="w-full bg-white border-2 border-[#e2e8f0] focus:border-[#231651] rounded-2xl py-3 px-4 text-sm font-semibold outline-none transition-all"
|
||||
className="w-full bg-white border-2 border-[#e2e8f0] focus:border-[#001828] rounded-2xl py-3 px-4 text-sm font-semibold outline-none transition-all"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
@@ -248,7 +248,7 @@ const Staff = () => {
|
||||
value={formData.email}
|
||||
onChange={(e) => setFormData({...formData, email: e.target.value})}
|
||||
placeholder="staff@rit.edu"
|
||||
className="w-full bg-white border-2 border-[#e2e8f0] focus:border-[#231651] rounded-2xl py-3 pl-11 pr-4 text-sm font-semibold outline-none transition-all"
|
||||
className="w-full bg-white border-2 border-[#e2e8f0] focus:border-[#001828] rounded-2xl py-3 pl-11 pr-4 text-sm font-semibold outline-none transition-all"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -266,7 +266,7 @@ const Staff = () => {
|
||||
value={formData.password}
|
||||
onChange={(e) => setFormData({...formData, password: e.target.value})}
|
||||
placeholder="••••••••"
|
||||
className="w-full bg-white border-2 border-[#e2e8f0] focus:border-[#231651] rounded-2xl py-3 pl-11 pr-4 text-sm font-semibold outline-none transition-all"
|
||||
className="w-full bg-white border-2 border-[#e2e8f0] focus:border-[#001828] rounded-2xl py-3 pl-11 pr-4 text-sm font-semibold outline-none transition-all"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -274,7 +274,7 @@ const Staff = () => {
|
||||
<div className="flex items-center gap-3 py-2">
|
||||
<div
|
||||
onClick={() => setFormData({...formData, viewOnly: !formData.viewOnly})}
|
||||
className={`w-5 h-5 rounded border-2 flex items-center justify-center cursor-pointer transition-all ${formData.viewOnly ? "bg-[#231651] border-[#231651]" : "border-[#e2e8f0]"}`}
|
||||
className={`w-5 h-5 rounded border-2 flex items-center justify-center cursor-pointer transition-all ${formData.viewOnly ? "bg-[#001828] border-[#001828]" : "border-[#e2e8f0]"}`}
|
||||
>
|
||||
{formData.viewOnly && <Check size={14} className="text-white" />}
|
||||
</div>
|
||||
@@ -284,7 +284,7 @@ const Staff = () => {
|
||||
<div className="pt-4 pb-2">
|
||||
<button
|
||||
type="submit"
|
||||
className="w-full bg-[#231651] text-white rounded-2xl py-4 font-black text-sm shadow-xl shadow-[#231651]/20 hover:scale-[1.02] active:scale-[0.98] transition-all"
|
||||
className="w-full bg-[#001828] text-white rounded-2xl py-4 font-black text-sm shadow-xl shadow-[#001828]/20 hover:scale-[1.02] active:scale-[0.98] transition-all"
|
||||
>
|
||||
Create Staff Account
|
||||
</button>
|
||||
|
||||
@@ -271,7 +271,7 @@ const Stalls: React.FC = () => {
|
||||
{/* Header Section */}
|
||||
<div className="flex flex-col md:flex-row md:items-center justify-between gap-6 max-w-[1600px]">
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="w-14 h-14 bg-[#231651] rounded-xl flex items-center justify-center shadow-lg shadow-[#231651]/20">
|
||||
<div className="w-14 h-14 bg-[#001828] rounded-xl flex items-center justify-center shadow-lg shadow-[#001828]/20">
|
||||
<Store className="text-white w-7 h-7" />
|
||||
</div>
|
||||
<div>
|
||||
@@ -282,13 +282,13 @@ const Stalls: React.FC = () => {
|
||||
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="relative group min-w-[320px]">
|
||||
<SearchIcon className="absolute left-3 top-1/2 -translate-y-1/2 text-[#94a3b8] group-focus-within:text-[#231651] transition-colors" size={18} />
|
||||
<SearchIcon className="absolute left-3 top-1/2 -translate-y-1/2 text-[#94a3b8] group-focus-within:text-[#001828] transition-colors" size={18} />
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Search stalls..."
|
||||
value={searchQuery}
|
||||
onChange={(e) => setSearchQuery(e.target.value)}
|
||||
className="w-full pl-10 pr-4 py-2 bg-white border border-[#e2e8f0] rounded-xl text-sm focus:outline-none focus:border-[#231651]/30 transition-all shadow-sm"
|
||||
className="w-full pl-10 pr-4 py-2 bg-white border border-[#e2e8f0] rounded-xl text-sm focus:outline-none focus:border-[#001828]/30 transition-all shadow-sm"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -305,7 +305,7 @@ const Stalls: React.FC = () => {
|
||||
});
|
||||
setIsModalOpen(true);
|
||||
}}
|
||||
className="px-6 py-2.5 bg-[#231651] text-white rounded-xl font-bold text-sm flex items-center gap-2 shadow-lg shadow-[#231651]/20 hover:scale-[1.01] active:scale-95 transition-all"
|
||||
className="px-6 py-2.5 bg-[#001828] text-white rounded-xl font-bold text-sm flex items-center gap-2 shadow-lg shadow-[#001828]/20 hover:scale-[1.01] active:scale-95 transition-all"
|
||||
>
|
||||
<Plus size={18} /> Add Stall
|
||||
</button>
|
||||
@@ -332,7 +332,7 @@ const Stalls: React.FC = () => {
|
||||
<div
|
||||
key={stall.id}
|
||||
onClick={() => openLinkModal(stall)}
|
||||
className="group cursor-pointer bg-white rounded-2xl overflow-hidden border border-[#e2e8f0] hover:border-[#231651]/30 transition-all hover:shadow-xl flex flex-col relative"
|
||||
className="group cursor-pointer bg-white rounded-2xl overflow-hidden border border-[#e2e8f0] hover:border-[#001828]/30 transition-all hover:shadow-xl flex flex-col relative"
|
||||
>
|
||||
{/* Image Section */}
|
||||
<div className="h-48 bg-slate-50 relative overflow-hidden flex items-center justify-center border-b border-[#e2e8f0]">
|
||||
@@ -397,7 +397,7 @@ const Stalls: React.FC = () => {
|
||||
<span className="text-sm font-bold text-[#1e293b]">{stall.baseItems?.length || 0}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-9 h-9 bg-gray-50 border border-[#e2e8f0] rounded-xl flex items-center justify-center text-[#231651] group-hover:border-[#231651] group-hover:bg-indigo-50 group-hover:text-indigo-600 transition-all shadow-sm">
|
||||
<div className="w-9 h-9 bg-gray-50 border border-[#e2e8f0] rounded-xl flex items-center justify-center text-[#001828] group-hover:border-[#001828] group-hover:bg-indigo-50 group-hover:text-indigo-600 transition-all shadow-sm">
|
||||
<Plus size={16} strokeWidth={3} />
|
||||
</div>
|
||||
</div>
|
||||
@@ -411,7 +411,7 @@ const Stalls: React.FC = () => {
|
||||
{/* Edit Stall Modal - Replicated from Customer Design */}
|
||||
<AnimatePresence>
|
||||
{isModalOpen && (
|
||||
<div className="fixed inset-0 bg-[#231651]/20 backdrop-blur-sm z-[100] flex items-center justify-center p-4 overflow-y-auto">
|
||||
<div className="fixed inset-0 bg-[#001828]/20 backdrop-blur-sm z-[100] flex items-center justify-center p-4 overflow-y-auto">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, scale: 0.95 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
@@ -420,7 +420,7 @@ const Stalls: React.FC = () => {
|
||||
>
|
||||
<div className="px-10 py-8 border-b border-[#e2e8f0] flex justify-between items-center bg-gray-50/50">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="w-12 h-12 bg-[#231651]/5 rounded-xl flex items-center justify-center text-[#231651]">
|
||||
<div className="w-12 h-12 bg-[#001828]/5 rounded-xl flex items-center justify-center text-[#001828]">
|
||||
<Store size={24} />
|
||||
</div>
|
||||
<div>
|
||||
@@ -442,7 +442,7 @@ const Stalls: React.FC = () => {
|
||||
type="text"
|
||||
value={formData.name}
|
||||
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
|
||||
className="w-full px-5 py-4 bg-slate-50 border border-[#e2e8f0] rounded-2xl text-base font-bold focus:ring-4 focus:ring-[#231651]/5 focus:border-[#231651] transition-all outline-none"
|
||||
className="w-full px-5 py-4 bg-slate-50 border border-[#e2e8f0] rounded-2xl text-base font-bold focus:ring-4 focus:ring-[#001828]/5 focus:border-[#001828] transition-all outline-none"
|
||||
placeholder="e.g. Continental Corner"
|
||||
/>
|
||||
</div>
|
||||
@@ -454,7 +454,7 @@ const Stalls: React.FC = () => {
|
||||
rows={3}
|
||||
value={formData.description}
|
||||
onChange={(e) => setFormData({ ...formData, description: e.target.value })}
|
||||
className="w-full px-5 py-4 bg-slate-50 border border-[#e2e8f0] rounded-2xl text-base font-bold focus:ring-4 focus:ring-[#231651]/5 focus:border-[#231651] transition-all outline-none resize-none"
|
||||
className="w-full px-5 py-4 bg-slate-50 border border-[#e2e8f0] rounded-2xl text-base font-bold focus:ring-4 focus:ring-[#001828]/5 focus:border-[#001828] transition-all outline-none resize-none"
|
||||
placeholder="Briefly describe the counter's specialty..."
|
||||
/>
|
||||
</div>
|
||||
@@ -546,7 +546,7 @@ const Stalls: React.FC = () => {
|
||||
<button
|
||||
type="submit"
|
||||
disabled={isSaving}
|
||||
className="flex-[1.5] px-8 py-4 bg-[#231651] text-white font-bold rounded-2xl shadow-xl shadow-[#231651]/20 hover:scale-[1.01] active:scale-95 transition-all flex items-center justify-center gap-3 text-sm"
|
||||
className="flex-[1.5] px-8 py-4 bg-[#001828] text-white font-bold rounded-2xl shadow-xl shadow-[#001828]/20 hover:scale-[1.01] active:scale-95 transition-all flex items-center justify-center gap-3 text-sm"
|
||||
>
|
||||
{isSaving ? (
|
||||
<><Loader2 size={20} className="animate-spin" /> Saving...</>
|
||||
@@ -564,7 +564,7 @@ const Stalls: React.FC = () => {
|
||||
{/* Item Configuration Modal - Resized but same style */}
|
||||
<AnimatePresence>
|
||||
{isItemModalOpen && selectedStall && (
|
||||
<div className="fixed inset-0 bg-[#231651]/20 backdrop-blur-sm z-[150] flex items-center justify-center p-4 overflow-y-auto">
|
||||
<div className="fixed inset-0 bg-[#001828]/20 backdrop-blur-sm z-[150] flex items-center justify-center p-4 overflow-y-auto">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, scale: 0.95, y: 30 }}
|
||||
animate={{ opacity: 1, scale: 1, y: 0 }}
|
||||
@@ -573,7 +573,7 @@ const Stalls: React.FC = () => {
|
||||
>
|
||||
<div className="px-10 py-8 border-b border-[#e2e8f0] flex justify-between items-center bg-gray-50/50">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="w-12 h-12 bg-[#231651]/5 rounded-xl flex items-center justify-center text-[#231651]">
|
||||
<div className="w-12 h-12 bg-[#001828]/5 rounded-xl flex items-center justify-center text-[#001828]">
|
||||
<Package size={24} />
|
||||
</div>
|
||||
<div>
|
||||
@@ -593,7 +593,7 @@ const Stalls: React.FC = () => {
|
||||
<button
|
||||
onClick={() => setActiveTab('products')}
|
||||
className={`px-8 py-2.5 rounded-lg text-xs font-bold transition-all ${
|
||||
activeTab === 'products' ? 'bg-[#231651] text-white shadow-md' : 'text-[#64748b] hover:text-[#231651]'
|
||||
activeTab === 'products' ? 'bg-[#001828] text-white shadow-md' : 'text-[#64748b] hover:text-[#001828]'
|
||||
}`}
|
||||
>
|
||||
Products ({allProducts.length})
|
||||
@@ -601,7 +601,7 @@ const Stalls: React.FC = () => {
|
||||
<button
|
||||
onClick={() => setActiveTab('baseItems')}
|
||||
className={`px-8 py-2.5 rounded-lg text-xs font-bold transition-all ${
|
||||
activeTab === 'baseItems' ? 'bg-[#231651] text-white shadow-md' : 'text-[#64748b] hover:text-[#231651]'
|
||||
activeTab === 'baseItems' ? 'bg-[#001828] text-white shadow-md' : 'text-[#64748b] hover:text-[#001828]'
|
||||
}`}
|
||||
>
|
||||
Base Items ({allBaseItems.length})
|
||||
@@ -615,7 +615,7 @@ const Stalls: React.FC = () => {
|
||||
placeholder={`Search ${activeTab === 'products' ? 'products' : 'items'}...`}
|
||||
value={itemSearchQuery}
|
||||
onChange={(e) => setItemSearchQuery(e.target.value)}
|
||||
className="w-full pl-12 pr-4 py-2 bg-white border border-[#e2e8f0] rounded-xl text-sm focus:outline-none focus:border-[#231651] transition-all"
|
||||
className="w-full pl-12 pr-4 py-2 bg-white border border-[#e2e8f0] rounded-xl text-sm focus:outline-none focus:border-[#001828] transition-all"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -632,10 +632,10 @@ const Stalls: React.FC = () => {
|
||||
<div
|
||||
key={product.id}
|
||||
onClick={() => setTempProductIds(prev => isSelected ? prev.filter(id => id !== product.id) : [...prev, product.id])}
|
||||
className={`p-5 rounded-xl border-2 transition-all flex items-center justify-between cursor-pointer group hover:scale-[1.01] ${isSelected ? 'bg-white border-[#231651] shadow-lg shadow-[#231651]/5' : 'bg-white border-transparent hover:border-[#e2e8f0]'}`}
|
||||
className={`p-5 rounded-xl border-2 transition-all flex items-center justify-between cursor-pointer group hover:scale-[1.01] ${isSelected ? 'bg-white border-[#001828] shadow-lg shadow-[#001828]/5' : 'bg-white border-transparent hover:border-[#e2e8f0]'}`}
|
||||
>
|
||||
<div className="flex items-center gap-4">
|
||||
<div className={`w-11 h-11 rounded-lg flex items-center justify-center transition-colors ${isSelected ? 'bg-[#231651] text-white' : 'bg-gray-100 text-slate-400'}`}>
|
||||
<div className={`w-11 h-11 rounded-lg flex items-center justify-center transition-colors ${isSelected ? 'bg-[#001828] text-white' : 'bg-gray-100 text-slate-400'}`}>
|
||||
<Package size={20} />
|
||||
</div>
|
||||
<div>
|
||||
@@ -643,7 +643,7 @@ const Stalls: React.FC = () => {
|
||||
<p className="text-[10px] font-bold text-[#94a3b8] uppercase tracking-wider">₹{product.price} • {product.category}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className={`w-6 h-6 rounded flex items-center justify-center border-2 transition-all ${isSelected ? 'bg-[#231651] border-[#231651]' : 'border-slate-200 bg-white'}`}>
|
||||
<div className={`w-6 h-6 rounded flex items-center justify-center border-2 transition-all ${isSelected ? 'bg-[#001828] border-[#001828]' : 'border-slate-200 bg-white'}`}>
|
||||
{isSelected && <Check size={14} className="text-white" strokeWidth={4} />}
|
||||
</div>
|
||||
</div>
|
||||
@@ -658,15 +658,15 @@ const Stalls: React.FC = () => {
|
||||
<div
|
||||
key={baseItem.id}
|
||||
onClick={() => setTempBaseItemIds(prev => isSelected ? prev.filter(id => id !== baseItem.id) : [...prev, baseItem.id])}
|
||||
className={`p-5 rounded-xl border-2 transition-all flex items-center justify-between cursor-pointer group hover:scale-[1.01] ${isSelected ? 'bg-white border-[#231651] shadow-lg shadow-[#231651]/5' : 'bg-white border-transparent hover:border-[#e2e8f0]'}`}
|
||||
className={`p-5 rounded-xl border-2 transition-all flex items-center justify-between cursor-pointer group hover:scale-[1.01] ${isSelected ? 'bg-white border-[#001828] shadow-lg shadow-[#001828]/5' : 'bg-white border-transparent hover:border-[#e2e8f0]'}`}
|
||||
>
|
||||
<div className="flex items-center gap-4">
|
||||
<div className={`w-11 h-11 rounded-lg flex items-center justify-center transition-colors ${isSelected ? 'bg-[#231651] text-white' : 'bg-gray-100 text-slate-400'}`}>
|
||||
<div className={`w-11 h-11 rounded-lg flex items-center justify-center transition-colors ${isSelected ? 'bg-[#001828] text-white' : 'bg-gray-100 text-slate-400'}`}>
|
||||
<Layers size={20} />
|
||||
</div>
|
||||
<p className="font-bold text-[#1e293b] text-sm">{baseItem.name}</p>
|
||||
</div>
|
||||
<div className={`w-6 h-6 rounded flex items-center justify-center border-2 transition-all ${isSelected ? 'bg-[#231651] border-[#231651]' : 'border-slate-200 bg-white'}`}>
|
||||
<div className={`w-6 h-6 rounded flex items-center justify-center border-2 transition-all ${isSelected ? 'bg-[#001828] border-[#001828]' : 'border-slate-200 bg-white'}`}>
|
||||
{isSelected && <Check size={14} className="text-white" strokeWidth={4} />}
|
||||
</div>
|
||||
</div>
|
||||
@@ -682,7 +682,7 @@ const Stalls: React.FC = () => {
|
||||
<div className="flex items-center gap-6">
|
||||
<div className="flex flex-col">
|
||||
<span className="text-[10px] uppercase font-bold text-[#94a3b8] tracking-widest">Active Selections</span>
|
||||
<span className="text-sm font-bold text-[#231651]">{tempProductIds.length} Products, {tempBaseItemIds.length} Items</span>
|
||||
<span className="text-sm font-bold text-[#001828]">{tempProductIds.length} Products, {tempBaseItemIds.length} Items</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -693,7 +693,7 @@ const Stalls: React.FC = () => {
|
||||
<button
|
||||
onClick={saveItemAssociations}
|
||||
disabled={isSaving}
|
||||
className="px-8 py-2.5 bg-[#231651] text-white font-bold rounded-xl shadow-lg shadow-[#231651]/20 hover:scale-[1.02] active:scale-95 transition-all text-sm flex items-center gap-2"
|
||||
className="px-8 py-2.5 bg-[#001828] text-white font-bold rounded-xl shadow-lg shadow-[#001828]/20 hover:scale-[1.02] active:scale-95 transition-all text-sm flex items-center gap-2"
|
||||
>
|
||||
{isSaving ? <Loader2 size={16} className="animate-spin" /> : <><Check size={16} strokeWidth={3} /> Save Inventory</>}
|
||||
</button>
|
||||
@@ -707,7 +707,7 @@ const Stalls: React.FC = () => {
|
||||
{/* Session Configuration Modal */}
|
||||
<AnimatePresence>
|
||||
{showSessionModal && (
|
||||
<div className="fixed inset-0 bg-[#231651]/40 backdrop-blur-md z-[200] flex items-center justify-center p-4">
|
||||
<div className="fixed inset-0 bg-[#001828]/40 backdrop-blur-md z-[200] flex items-center justify-center p-4">
|
||||
<motion.div
|
||||
initial={{ scale: 0.9, opacity: 0 }}
|
||||
animate={{ scale: 1, opacity: 1 }}
|
||||
@@ -771,7 +771,7 @@ const Stalls: React.FC = () => {
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end gap-4 mt-10">
|
||||
<button onClick={() => setShowSessionModal(false)} className="px-10 py-4 bg-[#231651] text-white font-bold rounded-2xl shadow-xl shadow-[#231651]/20 hover:scale-[1.02] active:scale-95 transition-all">
|
||||
<button onClick={() => setShowSessionModal(false)} className="px-10 py-4 bg-[#001828] text-white font-bold rounded-2xl shadow-xl shadow-[#001828]/20 hover:scale-[1.02] active:scale-95 transition-all">
|
||||
Done
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -116,7 +116,7 @@ const StoreDashboard = () => {
|
||||
}
|
||||
|
||||
if (data.storeOverview && data.storeOverview.length > 0) {
|
||||
const ritStore = data.storeOverview.find((s: any) => s.name === 'RIT Canteen');
|
||||
const ritStore = data.storeOverview.find((s: any) => s.name === 'Tillo Canteen');
|
||||
if (ritStore) {
|
||||
setStats(prev => ({
|
||||
...prev,
|
||||
|
||||
@@ -104,7 +104,7 @@ const Terminals = () => {
|
||||
whileHover={{ scale: 1.02 }}
|
||||
whileTap={{ scale: 0.98 }}
|
||||
onClick={() => setIsAddModalOpen(true)}
|
||||
className="flex items-center justify-center gap-2 bg-[#231651] text-white px-6 py-3.5 rounded-2xl font-bold shadow-lg shadow-[#231651]/20 hover:bg-[#2d1d66] transition-all"
|
||||
className="flex items-center justify-center gap-2 bg-[#001828] text-white px-6 py-3.5 rounded-2xl font-bold shadow-lg shadow-[#001828]/20 hover:bg-[#2d1d66] transition-all"
|
||||
>
|
||||
<Plus size={20} />
|
||||
Add Terminal
|
||||
@@ -113,7 +113,7 @@ const Terminals = () => {
|
||||
|
||||
{/* Stats/Info Banner */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
<div className="bg-gradient-to-br from-[#231651] to-[#3d2b7a] p-6 rounded-3xl text-white shadow-xl">
|
||||
<div className="bg-gradient-to-br from-[#001828] to-[#3d2b7a] p-6 rounded-3xl text-white shadow-xl">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="p-3 bg-white/10 rounded-2xl">
|
||||
<Monitor size={24} />
|
||||
@@ -146,9 +146,9 @@ const Terminals = () => {
|
||||
</div>
|
||||
|
||||
{/* Search and Filters */}
|
||||
<div className="bg-white p-2 rounded-2xl border border-gray-100 shadow-sm flex items-center group focus-within:ring-2 focus-within:ring-[#231651]/10 transition-all">
|
||||
<div className="bg-white p-2 rounded-2xl border border-gray-100 shadow-sm flex items-center group focus-within:ring-2 focus-within:ring-[#001828]/10 transition-all">
|
||||
<div className="p-3">
|
||||
<Search size={20} className="text-gray-400 group-focus-within:text-[#231651] transition-colors" />
|
||||
<Search size={20} className="text-gray-400 group-focus-within:text-[#001828] transition-colors" />
|
||||
</div>
|
||||
<input
|
||||
type="text"
|
||||
@@ -177,10 +177,10 @@ const Terminals = () => {
|
||||
setSelectedTerminal(terminal);
|
||||
setIsPinModalOpen(true);
|
||||
}}
|
||||
className="bg-white p-6 rounded-[2.5rem] border border-gray-100 shadow-sm hover:shadow-xl hover:shadow-[#231651]/5 transition-all cursor-pointer group relative overflow-hidden"
|
||||
className="bg-white p-6 rounded-[2.5rem] border border-gray-100 shadow-sm hover:shadow-xl hover:shadow-[#001828]/5 transition-all cursor-pointer group relative overflow-hidden"
|
||||
>
|
||||
{/* Card Background Pattern */}
|
||||
<div className="absolute -right-8 -top-8 text-[#231651]/5 rotate-12 transition-transform group-hover:rotate-0 duration-500">
|
||||
<div className="absolute -right-8 -top-8 text-[#001828]/5 rotate-12 transition-transform group-hover:rotate-0 duration-500">
|
||||
<Monitor size={140} />
|
||||
</div>
|
||||
|
||||
@@ -189,7 +189,7 @@ const Terminals = () => {
|
||||
<div className={`p-4 rounded-2xl border transition-colors duration-300 ${
|
||||
terminal.paired
|
||||
? 'bg-green-50 text-green-600 border-green-200 group-hover:bg-green-600 group-hover:text-white'
|
||||
: 'bg-gray-50 text-[#231651] border-gray-200 group-hover:bg-[#231651] group-hover:text-white'
|
||||
: 'bg-gray-50 text-[#001828] border-gray-200 group-hover:bg-[#001828] group-hover:text-white'
|
||||
}`}>
|
||||
<Monitor size={28} />
|
||||
</div>
|
||||
@@ -213,7 +213,7 @@ const Terminals = () => {
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h4 className="text-xl font-bold text-gray-900 group-hover:text-[#231651] transition-colors">{terminal.name}</h4>
|
||||
<h4 className="text-xl font-bold text-gray-900 group-hover:text-[#001828] transition-colors">{terminal.name}</h4>
|
||||
<div className="flex items-center gap-1.5 text-gray-500 mt-1 font-medium text-sm">
|
||||
<MapPin size={14} />
|
||||
<span>{terminal.location}</span>
|
||||
@@ -244,7 +244,7 @@ const Terminals = () => {
|
||||
</div>
|
||||
|
||||
{terminal.paired ? (
|
||||
<div className="flex items-center gap-2 text-[#231651] font-bold text-sm">
|
||||
<div className="flex items-center gap-2 text-[#001828] font-bold text-sm">
|
||||
<Key size={16} />
|
||||
<span>View API Key</span>
|
||||
<ExternalLink size={14} />
|
||||
@@ -276,7 +276,7 @@ const Terminals = () => {
|
||||
<p className="text-gray-500 max-w-xs text-center mt-1">Start by adding your first counter device terminal to manage device authentication.</p>
|
||||
<button
|
||||
onClick={() => setIsAddModalOpen(true)}
|
||||
className="mt-6 text-[#231651] font-bold hover:underline underline-offset-4"
|
||||
className="mt-6 text-[#001828] font-bold hover:underline underline-offset-4"
|
||||
>
|
||||
Add your first terminal
|
||||
</button>
|
||||
|
||||
@@ -74,7 +74,7 @@ const VendorDashboard = () => {
|
||||
<motion.div
|
||||
animate={{ scale: [1, 1.1, 1], opacity: [0.5, 1, 0.5] }}
|
||||
transition={{ repeat: Infinity, duration: 1.5 }}
|
||||
className="text-[#231651] font-black uppercase tracking-widest text-sm"
|
||||
className="text-[#001828] font-black uppercase tracking-widest text-sm"
|
||||
>
|
||||
Analyzing Supply Chain...
|
||||
</motion.div>
|
||||
@@ -88,7 +88,7 @@ const VendorDashboard = () => {
|
||||
<div className="p-8 space-y-8 animate-in fade-in duration-500">
|
||||
<div className="flex flex-col md:flex-row md:items-center justify-between gap-4">
|
||||
<div>
|
||||
<h1 className="text-2xl font-black text-[#231651] tracking-tight">Vendor Dashboard</h1>
|
||||
<h1 className="text-2xl font-black text-[#001828] tracking-tight">Vendor Dashboard</h1>
|
||||
<p className="text-[#64748b] text-sm font-medium">Monitoring procurement, supplier health, and order cycles.</p>
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
@@ -113,7 +113,7 @@ const VendorDashboard = () => {
|
||||
>
|
||||
<div className="flex items-center justify-between mb-8">
|
||||
<h3 className="text-lg font-bold text-[#1e293b] flex items-center gap-2">
|
||||
<BarChart3 size={18} className="text-[#231651]" />
|
||||
<BarChart3 size={18} className="text-[#001828]" />
|
||||
Purchase Trends
|
||||
</h3>
|
||||
</div>
|
||||
@@ -122,15 +122,15 @@ const VendorDashboard = () => {
|
||||
<AreaChart data={trends}>
|
||||
<defs>
|
||||
<linearGradient id="colorPurchases" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="5%" stopColor="#231651" stopOpacity={0.1}/>
|
||||
<stop offset="95%" stopColor="#231651" stopOpacity={0}/>
|
||||
<stop offset="5%" stopColor="#001828" stopOpacity={0.1}/>
|
||||
<stop offset="95%" stopColor="#001828" stopOpacity={0}/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<CartesianGrid strokeDasharray="3 3" vertical={false} stroke="#f1f5f9" />
|
||||
<XAxis dataKey="month" axisLine={false} tickLine={false} tick={{fill: '#94a3b8', fontSize: 11, fontWeight: 700}} dy={10} />
|
||||
<YAxis axisLine={false} tickLine={false} tick={{fill: '#94a3b8', fontSize: 11, fontWeight: 700}} />
|
||||
<Tooltip />
|
||||
<Area type="monotone" dataKey="purchases" stroke="#231651" strokeWidth={3} fillOpacity={1} fill="url(#colorPurchases)" />
|
||||
<Area type="monotone" dataKey="purchases" stroke="#001828" strokeWidth={3} fillOpacity={1} fill="url(#colorPurchases)" />
|
||||
</AreaChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
@@ -143,7 +143,7 @@ const VendorDashboard = () => {
|
||||
>
|
||||
<div className="flex items-center justify-between mb-8">
|
||||
<h3 className="text-lg font-bold text-[#1e293b] flex items-center gap-2">
|
||||
<ShoppingBag size={18} className="text-[#231651]" />
|
||||
<ShoppingBag size={18} className="text-[#001828]" />
|
||||
Orders by Volume
|
||||
</h3>
|
||||
</div>
|
||||
@@ -153,7 +153,7 @@ const VendorDashboard = () => {
|
||||
<XAxis dataKey="month" axisLine={false} tickLine={false} tick={{fill: '#94a3b8', fontSize: 11, fontWeight: 700}} dy={10} />
|
||||
<YAxis axisLine={false} tickLine={false} tick={{fill: '#94a3b8', fontSize: 11, fontWeight: 700}} />
|
||||
<Tooltip />
|
||||
<Bar dataKey="orders" fill="#231651" radius={[4, 4, 0, 0]} />
|
||||
<Bar dataKey="orders" fill="#001828" radius={[4, 4, 0, 0]} />
|
||||
</BarChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
@@ -171,7 +171,7 @@ const VendorDashboard = () => {
|
||||
{v.name.charAt(0)}
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm font-bold text-[#1e293b] group-hover:text-[#231651] transition-colors">{v.name}</p>
|
||||
<p className="text-sm font-bold text-[#1e293b] group-hover:text-[#001828] transition-colors">{v.name}</p>
|
||||
<p className="text-[10px] font-bold text-[#94a3b8] uppercase tracking-wider">{v.orders} Orders this month</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -159,7 +159,7 @@ const Vendors: React.FC = () => {
|
||||
<div className="flex flex-col h-full bg-[#f8fafc] p-8 gap-8 overflow-y-auto animate-slideUp font-inter relative">
|
||||
<div className="flex flex-col md:flex-row md:items-center justify-between gap-6 max-w-[1600px]">
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="w-14 h-14 bg-[#231651] rounded-xl flex items-center justify-center shadow-lg shadow-[#231651]/20">
|
||||
<div className="w-14 h-14 bg-[#001828] rounded-xl flex items-center justify-center shadow-lg shadow-[#001828]/20">
|
||||
<Building2 className="text-white w-7 h-7" />
|
||||
</div>
|
||||
<div>
|
||||
@@ -172,7 +172,7 @@ const Vendors: React.FC = () => {
|
||||
<button
|
||||
onClick={handleAddClick}
|
||||
title="Register a new supplier in the database"
|
||||
className="px-5 py-2.5 bg-[#231651] text-white rounded-xl text-sm font-bold flex items-center gap-2 hover:scale-105 transition-all shadow-lg shadow-[#231651]/20"
|
||||
className="px-5 py-2.5 bg-[#001828] text-white rounded-xl text-sm font-bold flex items-center gap-2 hover:scale-105 transition-all shadow-lg shadow-[#001828]/20"
|
||||
>
|
||||
<Plus size={18} />
|
||||
Add Vendor
|
||||
@@ -185,21 +185,21 @@ const Vendors: React.FC = () => {
|
||||
placeholder="Search vendors..."
|
||||
value={searchTerm}
|
||||
onChange={(e) => setSearchTerm(e.target.value)}
|
||||
className="w-full pl-10 pr-4 py-2.5 bg-white border border-[#e2e8f0] rounded-xl text-sm focus:outline-none focus:border-[#231651]/30 transition-all shadow-sm"
|
||||
className="w-full pl-10 pr-4 py-2.5 bg-white border border-[#e2e8f0] rounded-xl text-sm focus:outline-none focus:border-[#001828]/30 transition-all shadow-sm"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex p-1 bg-white border border-[#e2e8f0] rounded-xl shadow-sm">
|
||||
<button
|
||||
title="Table View"
|
||||
className={`p-1.5 rounded-lg transition-all ${viewMode === 'table' ? 'bg-[#231651] text-white' : 'text-[#64748b] hover:bg-gray-50'}`}
|
||||
className={`p-1.5 rounded-lg transition-all ${viewMode === 'table' ? 'bg-[#001828] text-white' : 'text-[#64748b] hover:bg-gray-50'}`}
|
||||
onClick={() => setViewMode('table')}
|
||||
>
|
||||
<List size={20} />
|
||||
</button>
|
||||
<button
|
||||
title="Grid View"
|
||||
className={`p-1.5 rounded-lg transition-all ${viewMode === 'grid' ? 'bg-[#231651] text-white' : 'text-[#64748b] hover:bg-gray-50'}`}
|
||||
className={`p-1.5 rounded-lg transition-all ${viewMode === 'grid' ? 'bg-[#001828] text-white' : 'text-[#64748b] hover:bg-gray-50'}`}
|
||||
onClick={() => setViewMode('grid')}
|
||||
>
|
||||
<LayoutGrid size={20} />
|
||||
@@ -211,7 +211,7 @@ const Vendors: React.FC = () => {
|
||||
<div className="max-w-[1600px]">
|
||||
{isLoading ? (
|
||||
<div className="flex flex-col items-center justify-center py-24 bg-white rounded-xl border border-[#e2e8f0]">
|
||||
<div className="w-10 h-10 border-4 border-[#231651]/10 border-t-[#231651] rounded-full animate-spin"></div>
|
||||
<div className="w-10 h-10 border-4 border-[#001828]/10 border-t-[#001828] rounded-full animate-spin"></div>
|
||||
<p className="mt-4 text-[#64748b] font-medium text-sm">Loading vendors...</p>
|
||||
</div>
|
||||
) : (
|
||||
@@ -263,7 +263,7 @@ const Vendors: React.FC = () => {
|
||||
<button
|
||||
onClick={() => setOpenMenuId(openMenuId === vendor.id ? null : vendor.id)}
|
||||
title="Open actions menu"
|
||||
className="p-1.5 text-[#94a3b8] hover:text-[#231651] rounded-lg"
|
||||
className="p-1.5 text-[#94a3b8] hover:text-[#001828] rounded-lg"
|
||||
>
|
||||
<MoreVertical size={18} />
|
||||
</button>
|
||||
@@ -287,7 +287,7 @@ const Vendors: React.FC = () => {
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6 p-6">
|
||||
{filteredVendors.map(vendor => (
|
||||
<div key={vendor.id} className="p-6 bg-white border border-[#e2e8f0] rounded-2xl flex flex-col items-center text-center hover:shadow-xl transition-all hover:-translate-y-1">
|
||||
<div className="w-16 h-16 bg-[#231651] rounded-2xl flex items-center justify-center text-xl font-bold text-white mb-4">
|
||||
<div className="w-16 h-16 bg-[#001828] rounded-2xl flex items-center justify-center text-xl font-bold text-white mb-4">
|
||||
{vendor.name.charAt(0)}
|
||||
</div>
|
||||
<h3 className="text-lg font-bold text-[#1e293b]">{vendor.name}</h3>
|
||||
@@ -305,7 +305,7 @@ const Vendors: React.FC = () => {
|
||||
<button
|
||||
onClick={() => handleEditClick(vendor)}
|
||||
title="View and edit vendor profile"
|
||||
className="w-full mt-6 py-2.5 bg-gray-50 border border-[#e2e8f0] text-[#1e293b] hover:bg-[#231651] hover:text-white rounded-xl text-sm font-bold transition-all"
|
||||
className="w-full mt-6 py-2.5 bg-gray-50 border border-[#e2e8f0] text-[#1e293b] hover:bg-[#001828] hover:text-white rounded-xl text-sm font-bold transition-all"
|
||||
>
|
||||
Edit Details
|
||||
</button>
|
||||
@@ -326,11 +326,11 @@ const Vendors: React.FC = () => {
|
||||
</div>
|
||||
|
||||
{showModal && (
|
||||
<div className="fixed inset-0 bg-[#231651]/20 backdrop-blur-sm z-[100] flex items-center justify-center p-4">
|
||||
<div className="fixed inset-0 bg-[#001828]/20 backdrop-blur-sm z-[100] flex items-center justify-center p-4">
|
||||
<div className="bg-white rounded-3xl w-full max-w-xl shadow-2xl overflow-hidden animate-in zoom-in duration-300">
|
||||
<div className="px-8 py-6 border-b border-[#e2e8f0] flex justify-between items-center bg-gray-50/50">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="w-10 h-10 bg-[#231651] rounded-xl flex items-center justify-center text-white">
|
||||
<div className="w-10 h-10 bg-[#001828] rounded-xl flex items-center justify-center text-white">
|
||||
<Building2 size={20} />
|
||||
</div>
|
||||
<div>
|
||||
@@ -352,7 +352,7 @@ const Vendors: React.FC = () => {
|
||||
type="text"
|
||||
value={form.name}
|
||||
onChange={(e) => setForm({...form, name: e.target.value})}
|
||||
className="w-full px-4 py-3 bg-slate-50 border border-[#e2e8f0] rounded-xl text-sm font-bold focus:border-[#231651] outline-none transition-all"
|
||||
className="w-full px-4 py-3 bg-slate-50 border border-[#e2e8f0] rounded-xl text-sm font-bold focus:border-[#001828] outline-none transition-all"
|
||||
placeholder="e.g. Fresh Foods Ltd"
|
||||
/>
|
||||
</div>
|
||||
@@ -362,7 +362,7 @@ const Vendors: React.FC = () => {
|
||||
type="text"
|
||||
value={form.companyName}
|
||||
onChange={(e) => setForm({...form, companyName: e.target.value})}
|
||||
className="w-full px-4 py-3 bg-slate-50 border border-[#e2e8f0] rounded-xl text-sm font-bold focus:border-[#231651] outline-none transition-all"
|
||||
className="w-full px-4 py-3 bg-slate-50 border border-[#e2e8f0] rounded-xl text-sm font-bold focus:border-[#001828] outline-none transition-all"
|
||||
placeholder="Official company name"
|
||||
/>
|
||||
</div>
|
||||
@@ -374,7 +374,7 @@ const Vendors: React.FC = () => {
|
||||
type="text"
|
||||
value={form.contactNumber}
|
||||
onChange={(e) => setForm({...form, contactNumber: e.target.value})}
|
||||
className="w-full px-4 py-3 bg-slate-50 border border-[#e2e8f0] rounded-xl text-sm font-bold focus:border-[#231651] outline-none transition-all"
|
||||
className="w-full px-4 py-3 bg-slate-50 border border-[#e2e8f0] rounded-xl text-sm font-bold focus:border-[#001828] outline-none transition-all"
|
||||
placeholder="Phone number"
|
||||
/>
|
||||
</div>
|
||||
@@ -384,7 +384,7 @@ const Vendors: React.FC = () => {
|
||||
type="email"
|
||||
value={form.email}
|
||||
onChange={(e) => setForm({...form, email: e.target.value})}
|
||||
className="w-full px-4 py-3 bg-slate-50 border border-[#e2e8f0] rounded-xl text-sm font-bold focus:border-[#231651] outline-none transition-all"
|
||||
className="w-full px-4 py-3 bg-slate-50 border border-[#e2e8f0] rounded-xl text-sm font-bold focus:border-[#001828] outline-none transition-all"
|
||||
placeholder="vendor@email.com"
|
||||
/>
|
||||
</div>
|
||||
@@ -404,7 +404,7 @@ const Vendors: React.FC = () => {
|
||||
type="submit"
|
||||
disabled={isSaving}
|
||||
title={editingVendor ? "Update vendor records" : "Save new vendor"}
|
||||
className="flex-[1.5] px-6 py-3 bg-[#231651] text-white font-bold rounded-xl shadow-lg shadow-[#231651]/20 flex items-center justify-center gap-2 hover:scale-[1.02] transition-all text-sm"
|
||||
className="flex-[1.5] px-6 py-3 bg-[#001828] text-white font-bold rounded-xl shadow-lg shadow-[#001828]/20 flex items-center justify-center gap-2 hover:scale-[1.02] transition-all text-sm"
|
||||
>
|
||||
{isSaving ? <Loader2 size={18} className="animate-spin" /> : editingVendor ? 'Update Vendor' : 'Create Vendor'}
|
||||
</button>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>RIT Canteen</title>
|
||||
<title>Tillo Canteen</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 155 KiB After Width: | Height: | Size: 17 KiB |
@@ -182,7 +182,7 @@
|
||||
|
||||
[data-theme='dark'] .app-header .header-title,
|
||||
[data-theme='dark'] .app-header .location-label {
|
||||
color: #231651;
|
||||
color: #001828;
|
||||
}
|
||||
|
||||
[data-theme='dark'] .app-header .location-sub {
|
||||
@@ -192,7 +192,7 @@
|
||||
[data-theme='dark'] .app-header .back-button,
|
||||
[data-theme='dark'] .app-header .icon-button:not(.profile) {
|
||||
background-color: #f0f1ff;
|
||||
color: #231651;
|
||||
color: #001828;
|
||||
}
|
||||
|
||||
[data-theme='dark'] .app-header .search-bar {
|
||||
@@ -201,6 +201,6 @@
|
||||
}
|
||||
|
||||
[data-theme='dark'] .app-header .cart-count {
|
||||
background-color: #231651;
|
||||
background-color: #001828;
|
||||
color: white;
|
||||
}
|
||||
|
||||
@@ -22,13 +22,13 @@ const Header: React.FC<HeaderProps> = ({ title, onBack, showCart = true }) => {
|
||||
return (
|
||||
<header className="app-header">
|
||||
<div className="header-left">
|
||||
{onBack || (title && title !== "RIT Canteen") ? (
|
||||
{onBack || (title && title !== "Tillo Canteen") ? (
|
||||
<button onClick={handleBack} className="back-button">
|
||||
<ArrowLeft size={20} />
|
||||
</button>
|
||||
) : null}
|
||||
|
||||
{title && title !== "RIT Canteen" ? (
|
||||
{title && title !== "Tillo Canteen" ? (
|
||||
<h1 className="header-title">{title}</h1>
|
||||
) : (
|
||||
<img
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
:root {
|
||||
/* LIGHT THEME (Default) */
|
||||
--primary: #231651;
|
||||
--primary-rgb: 35, 22, 81;
|
||||
--primary-light: #f0f1ff;
|
||||
--primary: #08a850;
|
||||
--primary-rgb: 8, 168, 80;
|
||||
--primary-light: #f4fbf7;
|
||||
--bg: #f8f9fe;
|
||||
--surface: #ffffff;
|
||||
--border: rgba(35, 22, 81, 0.08);
|
||||
--green: #00B894;
|
||||
--green-light: #E6FFFA;
|
||||
--border: rgba(0, 24, 40, 0.08);
|
||||
--green: #08a850;
|
||||
--green-light: #f4fbf7;
|
||||
--red: #ff4d4f;
|
||||
--text-dark: #231651;
|
||||
--text-mid: #4a3e7a;
|
||||
--text-light: #7b71af;
|
||||
--text-dark: #001828;
|
||||
--text-mid: #475569;
|
||||
--text-light: #94a3b8;
|
||||
--star: #f4c640;
|
||||
--shadow: 0 4px 20px rgba(35, 22, 81, 0.05);
|
||||
--shadow: 0 4px 20px rgba(0, 24, 40, 0.04);
|
||||
--input-bg: #f8f9ff;
|
||||
--modal-overlay: rgba(35, 22, 81, 0.3);
|
||||
--modal-overlay: rgba(0, 24, 40, 0.3);
|
||||
}
|
||||
|
||||
[data-theme='dark'] {
|
||||
|
||||
@@ -236,7 +236,7 @@
|
||||
.suspension-close-btn {
|
||||
width: 100%;
|
||||
padding: 16px;
|
||||
background: #231651;
|
||||
background: #001828;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 16px;
|
||||
|
||||
@@ -215,7 +215,7 @@ const LoginScreen: React.FC = () => {
|
||||
|
||||
<div className="login-footer-info">
|
||||
<p>© 2026 Rajalakshmi Institute of Technology</p>
|
||||
<p>RIT Canteen Management System</p>
|
||||
<p>Tillo Canteen Management System</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -226,7 +226,7 @@ const LoginScreen: React.FC = () => {
|
||||
<Lock size={40} />
|
||||
</div>
|
||||
<h2>Account Suspended</h2>
|
||||
<p>Your access to the RIT Canteen system has been restricted by an administrator.</p>
|
||||
<p>Your access to the Tillo Canteen system has been restricted by an administrator.</p>
|
||||
<div className="suspension-details">
|
||||
<span>Please contact the Admin or Manager to resolve this issue.</span>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user