Vendor Dashboard and Store dashboard added

This commit is contained in:
Sidharth Prabhu
2026-04-09 15:35:42 +05:30
parent dd3e811cdf
commit 4dc0b37bad
9 changed files with 68 additions and 57 deletions

0
backend/mvnw vendored Normal file → Executable file
View File

View File

@@ -4,6 +4,7 @@ import com.rit.canteen.sales.model.SystemUser;
import com.rit.canteen.sales.repository.SystemUserRepository; import com.rit.canteen.sales.repository.SystemUserRepository;
import jakarta.annotation.PostConstruct; import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -19,6 +20,12 @@ public class SystemUserService {
@Autowired @Autowired
private BCryptPasswordEncoder passwordEncoder; private BCryptPasswordEncoder passwordEncoder;
@Value("${app.master.username:admin}")
private String masterUsername;
@Value("${app.master.password:admin}")
private String masterPassword;
@PostConstruct @PostConstruct
public void init() { public void init() {
// Handle migration from old credentials if they exist // Handle migration from old credentials if they exist
@@ -28,31 +35,31 @@ public class SystemUserService {
repository.delete(oldUser); repository.delete(oldUser);
System.out.println(">>> REMOVED OBSOLETE MASTER USER: admin@ritcanteen.com"); System.out.println(">>> REMOVED OBSOLETE MASTER USER: admin@ritcanteen.com");
} else { } else {
oldUser.setEmail("admin"); oldUser.setEmail(masterUsername);
oldUser.setPassword(passwordEncoder.encode("admin")); oldUser.setPassword(passwordEncoder.encode(masterPassword));
repository.save(oldUser); repository.save(oldUser);
System.out.println(">>> MIGRATED MASTER USER: admin / admin"); System.out.println(">>> MIGRATED MASTER USER: admin / admin");
} }
}); });
// Ensure 'admin' user exists and has the correct password // Ensure 'admin' user exists and has the correct password
Optional<SystemUser> adminUser = repository.findByEmail("admin"); Optional<SystemUser> adminUser = repository.findByEmail(masterUsername);
if (adminUser.isPresent()) { if (adminUser.isPresent()) {
SystemUser admin = adminUser.get(); SystemUser admin = adminUser.get();
admin.setPassword(passwordEncoder.encode("admin")); admin.setPassword(passwordEncoder.encode(masterPassword));
admin.setRole("MASTER"); admin.setRole("MASTER");
repository.save(admin); repository.save(admin);
System.out.println(">>> UPDATED MASTER USER PASSWORD: admin / admin"); System.out.println(">>> UPDATED MASTER USER PASSWORD: " + masterUsername + " / " + masterPassword);
} else { } else {
SystemUser master = new SystemUser(); SystemUser master = new SystemUser();
master.setName("Admin Master"); master.setName("Admin Master");
master.setEmail("admin"); master.setEmail(masterUsername);
master.setPassword(passwordEncoder.encode("admin")); master.setPassword(passwordEncoder.encode(masterPassword));
master.setRole("MASTER"); master.setRole("MASTER");
master.setPermissions(List.of("dashboard", "sale", "customers", "purchases", "inventory", "expense", "reports", "stores", "table", "wallet", "promotions", "feedback")); master.setPermissions(List.of("dashboard", "sale", "customers", "purchases", "inventory", "expense", "reports", "stores", "table", "wallet", "promotions", "feedback"));
master.setViewOnly(false); master.setViewOnly(false);
repository.save(master); repository.save(master);
System.out.println(">>> SEEDED MASTER USER: admin / admin"); System.out.println(">>> SEEDED MASTER USER: " + masterUsername + " / " + masterPassword);
} }
} }

View File

@@ -1,11 +1,15 @@
spring.application.name=backend spring.application.name=backend
server.address=0.0.0.0 server.address=0.0.0.0
spring.datasource.url=jdbc:postgresql://localhost:5432/canteen_automation spring.datasource.url=jdbc:postgresql://localhost:5432/positeasy
spring.datasource.username=postgres spring.datasource.username=postgres
spring.datasource.password=Abiram@07 spring.datasource.password=sidharth
spring.datasource.driver-class-name=org.postgresql.Driver spring.datasource.driver-class-name=org.postgresql.Driver
spring.jpa.hibernate.ddl-auto=update spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
# Master Account Credentials
app.master.username=admin
app.master.password=admin

View File

@@ -198,7 +198,7 @@ const Sidebar = () => {
className={cn( className={cn(
"w-full flex items-center justify-between p-2.5 rounded-xl text-sm font-semibold transition-all duration-200 group", "w-full flex items-center justify-between p-2.5 rounded-xl text-sm font-semibold transition-all duration-200 group",
openMenus.includes(item.title) openMenus.includes(item.title)
? "text-[#521c4b] bg-[#521c4b]/5" ? "text-[#0f4475] bg-[#0f4475]/5"
: "text-[#475569] hover:bg-gray-50 hover:text-[#1e293b]" : "text-[#475569] hover:bg-gray-50 hover:text-[#1e293b]"
)} )}
> >
@@ -234,7 +234,7 @@ const Sidebar = () => {
className={({ isActive }) => cn( className={({ isActive }) => cn(
"flex items-center gap-3 py-2 px-4 rounded-lg text-[13px] font-medium transition-all group relative", "flex items-center gap-3 py-2 px-4 rounded-lg text-[13px] font-medium transition-all group relative",
isActive isActive
? "text-white bg-[#521c4b] shadow-md shadow-[#521c4b]/10" ? "text-white bg-[#0f4475] shadow-md shadow-[#0f4475]/10"
: "text-[#64748b] hover:text-[#1e293b] hover:translate-x-1" : "text-[#64748b] hover:text-[#1e293b] hover:translate-x-1"
)} )}
> >
@@ -267,7 +267,7 @@ const Sidebar = () => {
className={({ isActive }) => cn( className={({ isActive }) => cn(
"flex items-center gap-3 p-2.5 rounded-xl text-sm font-semibold transition-all duration-200 group", "flex items-center gap-3 p-2.5 rounded-xl text-sm font-semibold transition-all duration-200 group",
isActive isActive
? "bg-[#521c4b] text-white shadow-lg shadow-[#521c4b]/15" ? "bg-[#0f4475] text-white shadow-lg shadow-[#0f4475]/15"
: "text-[#475569] hover:bg-gray-50 hover:text-[#1e293b]" : "text-[#475569] hover:bg-gray-50 hover:text-[#1e293b]"
)} )}
> >

View File

@@ -50,7 +50,7 @@ const Dashboard = () => {
<motion.div <motion.div
animate={{ scale: [1, 1.1, 1], opacity: [0.5, 1, 0.5] }} animate={{ scale: [1, 1.1, 1], opacity: [0.5, 1, 0.5] }}
transition={{ repeat: Infinity, duration: 1.5 }} transition={{ repeat: Infinity, duration: 1.5 }}
className="text-[#521c4b] font-black uppercase tracking-widest text-sm" className="text-[#0f4475] font-black uppercase tracking-widest text-sm"
> >
Loading Business Intelligence... Loading Business Intelligence...
</motion.div> </motion.div>
@@ -74,7 +74,7 @@ const Dashboard = () => {
<button title="Navigate back to previous section" className="p-1.5 hover:bg-slate-100 rounded-lg transition-all"> <button title="Navigate back to previous section" className="p-1.5 hover:bg-slate-100 rounded-lg transition-all">
<ArrowRight className="rotate-180 text-slate-400" size={18} /> <ArrowRight className="rotate-180 text-slate-400" size={18} />
</button> </button>
<h2 className="text-xs font-black text-[#521c4b] uppercase tracking-widest">Dashboard</h2> <h2 className="text-xs font-black text-[#0f4475] uppercase tracking-widest">Dashboard</h2>
</div> </div>
<h1 className="text-2xl font-black text-slate-800">Good morning</h1> <h1 className="text-2xl font-black text-slate-800">Good morning</h1>
<p className="text-[10px] text-slate-400 font-medium flex items-center gap-1.5"> <p className="text-[10px] text-slate-400 font-medium flex items-center gap-1.5">
@@ -85,7 +85,7 @@ const Dashboard = () => {
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<div className="relative group"> <div className="relative group">
<select title="Filter by store type or category" className="appearance-none bg-white border border-slate-200 rounded-xl px-4 py-2 pr-10 text-xs font-bold text-slate-600 outline-none focus:border-[#521c4b] transition-all cursor-pointer shadow-sm"> <select title="Filter by store type or category" className="appearance-none bg-white border border-slate-200 rounded-xl px-4 py-2 pr-10 text-xs font-bold text-slate-600 outline-none focus:border-[#0f4475] transition-all cursor-pointer shadow-sm">
<option>Store Type: All</option> <option>Store Type: All</option>
</select> </select>
<div className="absolute right-3 top-1/2 -translate-y-1/2 pointer-events-none"> <div className="absolute right-3 top-1/2 -translate-y-1/2 pointer-events-none">
@@ -105,11 +105,11 @@ const Dashboard = () => {
key={tab} key={tab}
title={`View ${tab} analysis and trends`} title={`View ${tab} analysis and trends`}
onClick={() => setActiveTab(tab)} onClick={() => setActiveTab(tab)}
className={`pb-4 text-[11px] font-black uppercase tracking-widest transition-all relative ${activeTab === tab ? 'text-[#521c4b]' : 'text-slate-400 hover:text-slate-600'}`} className={`pb-4 text-[11px] font-black uppercase tracking-widest transition-all relative ${activeTab === tab ? 'text-[#0f4475]' : 'text-slate-400 hover:text-slate-600'}`}
> >
{tab} {tab}
{activeTab === tab && ( {activeTab === tab && (
<motion.div layoutId="tabLineMain" className="absolute bottom-0 left-0 right-0 h-0.5 bg-[#521c4b]" /> <motion.div layoutId="tabLineMain" className="absolute bottom-0 left-0 right-0 h-0.5 bg-[#0f4475]" />
)} )}
</button> </button>
))} ))}
@@ -117,7 +117,7 @@ const Dashboard = () => {
<div className="flex items-center justify-end mb-4 gap-4"> <div className="flex items-center justify-end mb-4 gap-4">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<div className="w-2.5 h-2.5 rounded-full border-2 border-[#521c4b]/30 bg-[#521c4b]/10" /> <div className="w-2.5 h-2.5 rounded-full border-2 border-[#0f4475]/30 bg-[#0f4475]/10" />
<span className="text-[10px] font-black text-slate-400 uppercase tracking-widest">Today's Revenue</span> <span className="text-[10px] font-black text-slate-400 uppercase tracking-widest">Today's Revenue</span>
</div> </div>
</div> </div>
@@ -194,7 +194,7 @@ const Dashboard = () => {
key={range} key={range}
title={`Analyze data from ${range.toLowerCase()}`} title={`Analyze data from ${range.toLowerCase()}`}
onClick={() => setTimeRange(range)} onClick={() => setTimeRange(range)}
className={`whitespace-nowrap px-3 py-2 text-[10px] font-black uppercase tracking-widest transition-all rounded-xl ${timeRange === range ? 'text-white bg-[#521c4b] shadow-md shadow-[#521c4b]/20' : 'text-slate-400 hover:text-slate-600'}`} className={`whitespace-nowrap px-3 py-2 text-[10px] font-black uppercase tracking-widest transition-all rounded-xl ${timeRange === range ? 'text-white bg-[#0f4475] shadow-md shadow-[#0f4475]/20' : 'text-slate-400 hover:text-slate-600'}`}
> >
{range} {range}
</button> </button>
@@ -202,7 +202,7 @@ const Dashboard = () => {
</div> </div>
{/* Total Orders Card */} {/* Total Orders Card */}
<div title="View detailed order volume and throughput" className="bg-white p-6 rounded-[24px] border border-slate-100 shadow-sm relative h-[180px] flex flex-col justify-between group hover:border-[#521c4b]/30 transition-all cursor-pointer"> <div title="View detailed order volume and throughput" className="bg-white p-6 rounded-[24px] border border-slate-100 shadow-sm relative h-[180px] flex flex-col justify-between group hover:border-[#0f4475]/30 transition-all cursor-pointer">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<div className="p-2 bg-amber-50 text-amber-500 rounded-xl group-hover:scale-110 transition-transform"> <div className="p-2 bg-amber-50 text-amber-500 rounded-xl group-hover:scale-110 transition-transform">
<ShoppingBag size={20} /> <ShoppingBag size={20} />
@@ -216,9 +216,9 @@ const Dashboard = () => {
</div> </div>
{/* Expenses Card */} {/* Expenses Card */}
<div title="Track operational expenditures and overhead" className="bg-white p-6 rounded-[24px] border border-slate-100 shadow-sm h-[130px] flex flex-col justify-between group hover:border-[#521c4b]/30 transition-all cursor-pointer"> <div title="Track operational expenditures and overhead" className="bg-white p-6 rounded-[24px] border border-slate-100 shadow-sm h-[130px] flex flex-col justify-between group hover:border-[#0f4475]/30 transition-all cursor-pointer">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<div className="p-2 bg-slate-50 text-[#521c4b] rounded-xl shadow-sm group-hover:bg-[#521c4b]/10 transition-colors"> <div className="p-2 bg-slate-50 text-[#0f4475] rounded-xl shadow-sm group-hover:bg-[#0f4475]/10 transition-colors">
<Wallet size={20} /> <Wallet size={20} />
</div> </div>
<h4 className="text-[11px] font-black text-slate-400 uppercase tracking-widest leading-none">Total Expenses</h4> <h4 className="text-[11px] font-black text-slate-400 uppercase tracking-widest leading-none">Total Expenses</h4>
@@ -249,7 +249,7 @@ const Dashboard = () => {
))} ))}
</div> </div>
<div className="mt-8"> <div className="mt-8">
<button title="Refresh and sync comprehensive business insights" className="w-full py-3 border border-dashed border-slate-200 rounded-2xl text-[10px] font-black text-slate-400 uppercase tracking-widest hover:border-[#521c4b]/30 hover:text-[#521c4b] transition-all"> <button title="Refresh and sync comprehensive business insights" className="w-full py-3 border border-dashed border-slate-200 rounded-2xl text-[10px] font-black text-slate-400 uppercase tracking-widest hover:border-[#0f4475]/30 hover:text-[#0f4475] transition-all">
Generate More Insights Generate More Insights
</button> </button>
</div> </div>
@@ -259,15 +259,15 @@ const Dashboard = () => {
<div className="col-span-12 lg:col-span-7 bg-white rounded-[32px] border border-slate-100 shadow-sm p-8"> <div className="col-span-12 lg:col-span-7 bg-white rounded-[32px] border border-slate-100 shadow-sm p-8">
<div className="flex items-center justify-between mb-8"> <div className="flex items-center justify-between mb-8">
<h3 className="text-sm font-black text-slate-800 tracking-tight uppercase tracking-widest">Store Performance</h3> <h3 className="text-sm font-black text-slate-800 tracking-tight uppercase tracking-widest">Store Performance</h3>
<button title="View detailed metrics for all geographic locations" className="text-[10px] font-black text-[#521c4b] uppercase tracking-widest hover:underline">View All Locations</button> <button title="View detailed metrics for all geographic locations" className="text-[10px] font-black text-[#0f4475] uppercase tracking-widest hover:underline">View All Locations</button>
</div> </div>
<div className="space-y-6"> <div className="space-y-6">
{(storeOverview.length > 0 ? storeOverview : [{name: 'No active sales currently', sale: 0, orders: 0, taxes: 0, purchase: 0}]).map((store: any, idx: number) => ( {(storeOverview.length > 0 ? storeOverview : [{name: 'No active sales currently', sale: 0, orders: 0, taxes: 0, purchase: 0}]).map((store: any, idx: number) => (
<div key={idx} className="p-6 rounded-[28px] border border-slate-50 bg-slate-50/30 group hover:bg-white hover:shadow-lg hover:border-transparent transition-all border-l-4 border-l-[#521c4b]/30"> <div key={idx} className="p-6 rounded-[28px] border border-slate-50 bg-slate-50/30 group hover:bg-white hover:shadow-lg hover:border-transparent transition-all border-l-4 border-l-[#0f4475]/30">
<p className="text-xs font-black text-slate-800 mb-6 uppercase tracking-widest flex items-center justify-between"> <p className="text-xs font-black text-slate-800 mb-6 uppercase tracking-widest flex items-center justify-between">
{store.name} {store.name}
<ArrowRight size={14} className="opacity-0 group-hover:opacity-100 transition-opacity text-[#521c4b]" /> <ArrowRight size={14} className="opacity-0 group-hover:opacity-100 transition-opacity text-[#0f4475]" />
</p> </p>
<div className="grid grid-cols-4 gap-4"> <div className="grid grid-cols-4 gap-4">
<div className="space-y-1.5"> <div className="space-y-1.5">
@@ -292,7 +292,7 @@ const Dashboard = () => {
</div> </div>
<div className="mt-10 flex justify-center"> <div className="mt-10 flex justify-center">
<button title="Execute a granular comparison across different store cohorts" className="flex items-center gap-3 px-8 py-3 bg-[#521c4b] text-white text-[11px] font-black uppercase tracking-widest rounded-2xl shadow-xl shadow-[#521c4b]/20 hover:scale-105 transition-all group"> <button title="Execute a granular comparison across different store cohorts" className="flex items-center gap-3 px-8 py-3 bg-[#0f4475] text-white text-[11px] font-black uppercase tracking-widest rounded-2xl shadow-xl shadow-[#0f4475]/20 hover:scale-105 transition-all group">
Detailed Comparison Detailed Comparison
<ArrowRight size={16} className="group-hover:translate-x-1 transition-transform" /> <ArrowRight size={16} className="group-hover:translate-x-1 transition-transform" />
</button> </button>

View File

@@ -18,8 +18,8 @@ import buildingPhoto from '../assets/ritchennai.webp';
const Login = () => { const Login = () => {
const [role, setRole] = useState<'manager' | 'master'>('manager'); const [role, setRole] = useState<'manager' | 'master'>('manager');
const [showPassword, setShowPassword] = useState(false); const [showPassword, setShowPassword] = useState(false);
const [username, setUsername] = useState('admin'); const [username, setUsername] = useState('');
const [password, setPassword] = useState('admin'); const [password, setPassword] = useState('');
const navigate = useNavigate(); const navigate = useNavigate();
// Ensure any previous session is completely wiped out when arriving at the login screen // Ensure any previous session is completely wiped out when arriving at the login screen

View File

@@ -169,7 +169,7 @@ const PurchaseAnalytics = () => {
if (isLoading) { if (isLoading) {
return ( return (
<div className="h-full flex flex-col items-center justify-center gap-4"> <div className="h-full flex flex-col items-center justify-center gap-4">
<Loader2 className="animate-spin text-[#521c4b]" size={40} /> <Loader2 className="animate-spin text-[#0f4475]" size={40} />
<p className="text-sm font-bold text-slate-500 uppercase tracking-widest">Calculating Market Analytics...</p> <p className="text-sm font-bold text-slate-500 uppercase tracking-widest">Calculating Market Analytics...</p>
</div> </div>
); );
@@ -180,12 +180,12 @@ const PurchaseAnalytics = () => {
{/* Header */} {/* Header */}
<div className="flex flex-col md:flex-row md:items-center justify-between gap-4"> <div className="flex flex-col md:flex-row md:items-center justify-between gap-4">
<div> <div>
<h1 className="text-2xl font-black text-[#521c4b] tracking-tight uppercase">Purchase Analytics</h1> <h1 className="text-2xl font-black text-[#0f4475] tracking-tight uppercase">Purchase Analytics</h1>
<div className="flex items-center gap-2 mt-1"> <div className="flex items-center gap-2 mt-1">
<span className="bg-[#521c4b]/10 text-[#521c4b] text-[10px] font-bold px-2 py-0.5 rounded-full uppercase"> <span className="bg-[#0f4475]/10 text-[#0f4475] text-[10px] font-bold px-2 py-0.5 rounded-full uppercase">
Start: {format(dateRange.start, 'yyyy-MM-dd')} Start: {format(dateRange.start, 'yyyy-MM-dd')}
</span> </span>
<span className="bg-[#521c4b]/10 text-[#521c4b] text-[10px] font-bold px-2 py-0.5 rounded-full uppercase"> <span className="bg-[#0f4475]/10 text-[#0f4475] text-[10px] font-bold px-2 py-0.5 rounded-full uppercase">
End: {format(dateRange.end, 'yyyy-MM-dd')} End: {format(dateRange.end, 'yyyy-MM-dd')}
</span> </span>
</div> </div>
@@ -193,7 +193,7 @@ const PurchaseAnalytics = () => {
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<button <button
onClick={() => setFilterType('all')} onClick={() => setFilterType('all')}
className={`px-4 py-2 rounded-xl text-xs font-bold uppercase transition-all ${filterType === 'all' ? 'bg-[#521c4b] text-white shadow-lg' : 'bg-white border text-slate-500 border-slate-200 hover:bg-slate-50'}`} className={`px-4 py-2 rounded-xl text-xs font-bold uppercase transition-all ${filterType === 'all' ? 'bg-[#0f4475] text-white shadow-lg' : 'bg-white border text-slate-500 border-slate-200 hover:bg-slate-50'}`}
> >
Show All Show All
</button> </button>
@@ -230,7 +230,7 @@ const PurchaseAnalytics = () => {
<input <input
type="text" type="text"
placeholder="Search products..." placeholder="Search products..."
className="pl-9 pr-4 py-2 border border-[#e2e8f0] rounded-xl text-xs outline-none focus:border-[#521c4b]/30 transition-all font-medium" className="pl-9 pr-4 py-2 border border-[#e2e8f0] rounded-xl text-xs outline-none focus:border-[#0f4475]/30 transition-all font-medium"
value={searchTerm} value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)} onChange={(e) => setSearchTerm(e.target.value)}
/> />
@@ -253,7 +253,7 @@ const PurchaseAnalytics = () => {
) : ( ) : (
filteredAnalytics.map((item, idx) => ( filteredAnalytics.map((item, idx) => (
<tr key={idx} className="hover:bg-gray-50/50 transition-colors group"> <tr key={idx} className="hover:bg-gray-50/50 transition-colors group">
<td className="px-6 py-4"><p className="text-xs font-bold text-[#1e293b] group-hover:text-[#521c4b]">{item.product}</p></td> <td className="px-6 py-4"><p className="text-xs font-bold text-[#1e293b] group-hover:text-[#0f4475]">{item.product}</p></td>
<td className="px-6 py-4 text-xs font-bold text-[#475569]">{item.qty}</td> <td className="px-6 py-4 text-xs font-bold text-[#475569]">{item.qty}</td>
<td className="px-6 py-4 text-xs font-bold text-[#475569] text-right">{item.basePrice.toFixed(2)}</td> <td className="px-6 py-4 text-xs font-bold text-[#475569] text-right">{item.basePrice.toFixed(2)}</td>
<td className="px-6 py-4 text-right"> <td className="px-6 py-4 text-right">
@@ -285,7 +285,7 @@ const PurchaseAnalytics = () => {
<div className="grid grid-cols-2 gap-4"> <div className="grid grid-cols-2 gap-4">
<button <button
onClick={() => setFilterType('up')} onClick={() => setFilterType('up')}
className={`p-4 rounded-2xl flex flex-col items-center justify-center gap-2 transition-all cursor-pointer hover:border-[#521c4b]/50 border-2 ${filterType === 'up' ? 'bg-[#521c4b] text-white border-[#521c4b]' : 'bg-gray-50 text-slate-400 border-transparent hover:bg-slate-100'}`} className={`p-4 rounded-2xl flex flex-col items-center justify-center gap-2 transition-all cursor-pointer hover:border-[#0f4475]/50 border-2 ${filterType === 'up' ? 'bg-[#0f4475] text-white border-[#0f4475]' : 'bg-gray-50 text-slate-400 border-transparent hover:bg-slate-100'}`}
> >
<TrendingUp size={20} /> <TrendingUp size={20} />
<span className="text-[10px] font-bold uppercase tracking-wider">Inflation</span> <span className="text-[10px] font-bold uppercase tracking-wider">Inflation</span>

View File

@@ -53,7 +53,7 @@ const PurchaseSummary = () => {
<motion.div <motion.div
animate={{ scale: [1, 1.05, 1] }} animate={{ scale: [1, 1.05, 1] }}
transition={{ repeat: Infinity, duration: 2 }} transition={{ repeat: Infinity, duration: 2 }}
className="text-[#521c4b] font-black uppercase tracking-widest text-xs" className="text-[#0f4475] font-black uppercase tracking-widest text-xs"
> >
Compiling Fiscal Intelligence... Compiling Fiscal Intelligence...
</motion.div> </motion.div>
@@ -78,7 +78,7 @@ const PurchaseSummary = () => {
<button title="Back" className="p-1.5 hover:bg-slate-100 rounded-lg transition-all"> <button title="Back" className="p-1.5 hover:bg-slate-100 rounded-lg transition-all">
<ArrowRight className="rotate-180 text-slate-400" size={18} /> <ArrowRight className="rotate-180 text-slate-400" size={18} />
</button> </button>
<h2 className="text-xs font-black text-[#521c4b] uppercase tracking-widest">Purchases</h2> <h2 className="text-xs font-black text-[#0f4475] uppercase tracking-widest">Purchases</h2>
</div> </div>
<h1 className="text-2xl font-black text-slate-800">Summary</h1> <h1 className="text-2xl font-black text-slate-800">Summary</h1>
</div> </div>
@@ -88,7 +88,7 @@ const PurchaseSummary = () => {
<button <button
key={range} key={range}
onClick={() => setActiveRange(range)} onClick={() => setActiveRange(range)}
className={`px-4 py-2 text-[10px] font-black uppercase tracking-widest transition-all rounded-xl ${activeRange === range ? 'text-white bg-[#521c4b] shadow-md shadow-[#521c4b]/20' : 'text-slate-400 hover:text-slate-600'}`} className={`px-4 py-2 text-[10px] font-black uppercase tracking-widest transition-all rounded-xl ${activeRange === range ? 'text-white bg-[#0f4475] shadow-md shadow-[#0f4475]/20' : 'text-slate-400 hover:text-slate-600'}`}
> >
{range} {range}
</button> </button>
@@ -118,7 +118,7 @@ const PurchaseSummary = () => {
</motion.div> </motion.div>
))} ))}
<div className="col-span-2 bg-[#521c4b] p-6 rounded-[32px] shadow-lg shadow-[#521c4b]/20 text-white relative overflow-hidden group"> <div className="col-span-2 bg-[#0f4475] p-6 rounded-[32px] shadow-lg shadow-[#0f4475]/20 text-white relative overflow-hidden group">
<div className="absolute -right-8 -top-8 w-32 h-32 bg-white/10 rounded-full blur-3xl" /> <div className="absolute -right-8 -top-8 w-32 h-32 bg-white/10 rounded-full blur-3xl" />
<div className="relative z-10 flex items-end justify-between"> <div className="relative z-10 flex items-end justify-between">
<div> <div>
@@ -173,7 +173,7 @@ const PurchaseSummary = () => {
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
<div className="relative"> <div className="relative">
<Search className="absolute left-3 top-1/2 -translate-y-1/2 text-slate-400" size={14} /> <Search className="absolute left-3 top-1/2 -translate-y-1/2 text-slate-400" size={14} />
<input type="text" title="Search" placeholder="Filter bills..." className="pl-9 pr-4 py-2 bg-slate-50 border border-slate-100 rounded-xl text-xs font-bold outline-none focus:border-[#521c4b] transition-all" /> <input type="text" title="Search" placeholder="Filter bills..." className="pl-9 pr-4 py-2 bg-slate-50 border border-slate-100 rounded-xl text-xs font-bold outline-none focus:border-[#0f4475] transition-all" />
</div> </div>
<button title="Filter" className="p-2.5 bg-slate-50 rounded-xl text-slate-500 border border-slate-100"><Filter size={16} /></button> <button title="Filter" className="p-2.5 bg-slate-50 rounded-xl text-slate-500 border border-slate-100"><Filter size={16} /></button>
</div> </div>
@@ -205,7 +205,7 @@ const PurchaseSummary = () => {
</span> </span>
</td> </td>
<td className="px-6 py-5 text-right text-xs font-black text-rose-500">{bill.balance.toLocaleString()}</td> <td className="px-6 py-5 text-right text-xs font-black text-rose-500">{bill.balance.toLocaleString()}</td>
<td className="px-6 py-5 text-right text-xs font-black text-[#521c4b]">{bill.amount.toLocaleString()}</td> <td className="px-6 py-5 text-right text-xs font-black text-[#0f4475]">{bill.amount.toLocaleString()}</td>
</tr> </tr>
))} ))}
</tbody> </tbody>

View File

@@ -100,7 +100,7 @@ const StoreDashboard = () => {
<button title="Return to previous screen" className="p-1.5 hover:bg-slate-100 rounded-lg transition-all"> <button title="Return to previous screen" className="p-1.5 hover:bg-slate-100 rounded-lg transition-all">
<ArrowRight className="rotate-180 text-slate-400" size={18} /> <ArrowRight className="rotate-180 text-slate-400" size={18} />
</button> </button>
<h2 className="text-xs font-black text-[#521c4b] uppercase tracking-widest">Store Dashboard</h2> <h2 className="text-xs font-black text-[#0f4475] uppercase tracking-widest">Store Dashboard</h2>
</div> </div>
<h1 className="text-2xl font-black text-slate-800">Good morning, RIT Canteen</h1> <h1 className="text-2xl font-black text-slate-800">Good morning, RIT Canteen</h1>
</div> </div>
@@ -108,7 +108,7 @@ const StoreDashboard = () => {
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<div className="relative group"> <div className="relative group">
<select title="Switch established store location" className="appearance-none bg-white border border-slate-200 rounded-xl px-4 py-2 pr-10 text-xs font-bold text-slate-600 outline-none focus:border-[#521c4b] transition-all cursor-pointer shadow-sm"> <select title="Switch established store location" className="appearance-none bg-white border border-slate-200 rounded-xl px-4 py-2 pr-10 text-xs font-bold text-slate-600 outline-none focus:border-[#0f4475] transition-all cursor-pointer shadow-sm">
<option>RIT Canteen</option> <option>RIT Canteen</option>
</select> </select>
<div className="absolute right-3 top-1/2 -translate-y-1/2 pointer-events-none"> <div className="absolute right-3 top-1/2 -translate-y-1/2 pointer-events-none">
@@ -116,7 +116,7 @@ const StoreDashboard = () => {
</div> </div>
</div> </div>
<div className="relative group"> <div className="relative group">
<select title="Toggle between available display views" className="appearance-none bg-white border border-slate-200 rounded-xl px-4 py-2 pr-10 text-xs font-bold text-slate-600 outline-none focus:border-[#521c4b] transition-all cursor-pointer shadow-sm"> <select title="Toggle between available display views" className="appearance-none bg-white border border-slate-200 rounded-xl px-4 py-2 pr-10 text-xs font-bold text-slate-600 outline-none focus:border-[#0f4475] transition-all cursor-pointer shadow-sm">
<option>All</option> <option>All</option>
</select> </select>
<div className="absolute right-3 top-1/2 -translate-y-1/2 pointer-events-none"> <div className="absolute right-3 top-1/2 -translate-y-1/2 pointer-events-none">
@@ -132,7 +132,7 @@ const StoreDashboard = () => {
<Star size={18} fill="#f59e0b" /> <Star size={18} fill="#f59e0b" />
</button> </button>
</div> </div>
<div title="Authenticated User: Abiram" className="w-8 h-8 rounded-full bg-[#521c4b] text-white flex items-center justify-center font-bold text-sm shadow-md cursor-pointer hover:ring-2 ring-[#521c4b]/20 transition-all"> <div title="Authenticated User: Abiram" className="w-8 h-8 rounded-full bg-[#0f4475] text-white flex items-center justify-center font-bold text-sm shadow-md cursor-pointer hover:ring-2 ring-[#0f4475]/20 transition-all">
A A
</div> </div>
</div> </div>
@@ -148,11 +148,11 @@ const StoreDashboard = () => {
key={tab} key={tab}
title={`Visualize ${tab.toLowerCase()} throughput data`} title={`Visualize ${tab.toLowerCase()} throughput data`}
onClick={() => setActiveTab(tab)} onClick={() => setActiveTab(tab)}
className={`pb-4 text-[11px] font-black uppercase tracking-widest transition-all relative ${activeTab === tab ? 'text-[#521c4b]' : 'text-slate-400 hover:text-slate-600'}`} className={`pb-4 text-[11px] font-black uppercase tracking-widest transition-all relative ${activeTab === tab ? 'text-[#0f4475]' : 'text-slate-400 hover:text-slate-600'}`}
> >
{tab} {tab}
{activeTab === tab && ( {activeTab === tab && (
<motion.div layoutId="tabLineStore" className="absolute bottom-0 left-0 right-0 h-0.5 bg-[#521c4b]" /> <motion.div layoutId="tabLineStore" className="absolute bottom-0 left-0 right-0 h-0.5 bg-[#0f4475]" />
)} )}
</button> </button>
))} ))}
@@ -224,18 +224,18 @@ const StoreDashboard = () => {
key={range} key={range}
title={`Filter metrics by ${range.toLowerCase()}`} title={`Filter metrics by ${range.toLowerCase()}`}
onClick={() => setTimeRange(range)} onClick={() => setTimeRange(range)}
className={`whitespace-nowrap px-2 py-2 text-[10px] font-black uppercase tracking-tighter transition-all relative ${timeRange === range ? 'text-[#521c4b]' : 'text-slate-400 hover:text-slate-600'}`} className={`whitespace-nowrap px-2 py-2 text-[10px] font-black uppercase tracking-tighter transition-all relative ${timeRange === range ? 'text-[#0f4475]' : 'text-slate-400 hover:text-slate-600'}`}
> >
{range} {range}
{timeRange === range && ( {timeRange === range && (
<motion.div layoutId="rangeLineStore" className="absolute bottom-0 left-0 right-0 h-0.5 bg-[#521c4b]" /> <motion.div layoutId="rangeLineStore" className="absolute bottom-0 left-0 right-0 h-0.5 bg-[#0f4475]" />
)} )}
</button> </button>
))} ))}
</div> </div>
{/* Total Orders Card */} {/* Total Orders Card */}
<div title="View detailed store volume and throughput" className="bg-white p-6 rounded-[24px] border border-slate-100 shadow-sm relative h-[180px] flex flex-col justify-between group cursor-pointer hover:border-[#521c4b]/30 transition-all"> <div title="View detailed store volume and throughput" className="bg-white p-6 rounded-[24px] border border-slate-100 shadow-sm relative h-[180px] flex flex-col justify-between group cursor-pointer hover:border-[#0f4475]/30 transition-all">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<div className="p-2 bg-amber-50 text-amber-500 rounded-xl group-hover:scale-110 transition-transform"> <div className="p-2 bg-amber-50 text-amber-500 rounded-xl group-hover:scale-110 transition-transform">
<ShoppingBag size={20} /> <ShoppingBag size={20} />
@@ -249,9 +249,9 @@ const StoreDashboard = () => {
</div> </div>
{/* Expenses Card */} {/* Expenses Card */}
<div title="Monitor store operational expenditures" className="bg-white p-6 rounded-[24px] border border-slate-100 shadow-sm h-[150px] flex flex-col justify-between group cursor-pointer hover:border-[#521c4b]/30 transition-all"> <div title="Monitor store operational expenditures" className="bg-white p-6 rounded-[24px] border border-slate-100 shadow-sm h-[150px] flex flex-col justify-between group cursor-pointer hover:border-[#0f4475]/30 transition-all">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<div className="p-2 bg-amber-100 text-[#521c4b] rounded-xl shadow-sm"> <div className="p-2 bg-amber-100 text-[#0f4475] rounded-xl shadow-sm">
<Wallet size={20} /> <Wallet size={20} />
</div> </div>
<h4 className="text-[11px] font-black text-slate-400 uppercase tracking-widest leading-none">Expenses</h4> <h4 className="text-[11px] font-black text-slate-400 uppercase tracking-widest leading-none">Expenses</h4>
@@ -297,7 +297,7 @@ const StoreDashboard = () => {
<img src={item.image} alt={item.name} className="w-full h-full object-cover" /> <img src={item.image} alt={item.name} className="w-full h-full object-cover" />
</div> </div>
<div className="space-y-0.5"> <div className="space-y-0.5">
<p className="text-[9px] font-black text-[#521c4b] uppercase tracking-widest brightness-110">{item.category}</p> <p className="text-[9px] font-black text-[#0f4475] uppercase tracking-widest brightness-110">{item.category}</p>
<p className="text-xs font-black text-slate-800 uppercase tracking-tight">{item.name}</p> <p className="text-xs font-black text-slate-800 uppercase tracking-tight">{item.name}</p>
</div> </div>
</div> </div>
@@ -328,7 +328,7 @@ const StoreDashboard = () => {
</div> </div>
<div className="mt-8 flex justify-end"> <div className="mt-8 flex justify-end">
<button title="Analyze subsequent business cycles" className="flex items-center gap-2 px-6 py-2.5 bg-[#521c4b]/5 hover:bg-[#521c4b]/10 text-[#521c4b] text-[11px] font-black uppercase tracking-widest rounded-2xl transition-all group"> <button title="Analyze subsequent business cycles" className="flex items-center gap-2 px-6 py-2.5 bg-[#0f4475]/5 hover:bg-[#0f4475]/10 text-[#0f4475] text-[11px] font-black uppercase tracking-widest rounded-2xl transition-all group">
Next Next
<ArrowRight size={14} className="group-hover:translate-x-1 transition-transform" /> <ArrowRight size={14} className="group-hover:translate-x-1 transition-transform" />
</button> </button>