mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 12:41:04 +00:00
update main color
This commit is contained in:
@@ -147,7 +147,7 @@ Each feature folder typically contains: `*Page.tsx` (list), `*DetailPage.tsx`, `
|
||||
|
||||
`DashboardLayout` provides the sidebar + header shell shared across all freight and passenger web apps:
|
||||
|
||||
- **Sidebar** — brand-tinted, icon-led navigation; the brand color (`#33578D`) marks the active item.
|
||||
- **Sidebar** — brand-tinted, icon-led navigation. Main brand color: `#10B981` (`rgb(16, 185, 129)` — emerald-500). Icon containers use the filled style: brand-color background with a white icon.
|
||||
- **Header** — language picker, notifications, user dropdown (click-driven, click-outside / Escape close); host apps opt into a light/dark theme toggle via `enableThemeToggle` (Tailwind class-based, persisted in `localStorage`).
|
||||
|
||||
### Auth integration (planned)
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
}
|
||||
|
||||
*::-webkit-scrollbar-thumb:hover {
|
||||
background-color: rgb(51 87 141 / 0.5);
|
||||
background-color: rgb(16 185 129 / 0.5);
|
||||
}
|
||||
|
||||
*::-webkit-scrollbar-corner {
|
||||
@@ -38,5 +38,5 @@
|
||||
}
|
||||
|
||||
.dark *::-webkit-scrollbar-thumb:hover {
|
||||
background-color: rgb(51 87 141 / 0.7);
|
||||
background-color: rgb(16 185 129 / 0.7);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ export default function Breadcrumbs({ items }: BreadcrumbsProps) {
|
||||
<Link
|
||||
to="/"
|
||||
aria-label="Home"
|
||||
className="flex items-center transition hover:text-[#33578D]"
|
||||
className="flex items-center transition hover:text-[#10B981]"
|
||||
>
|
||||
{/* <Home className="h-4 w-4" /> */}
|
||||
Dashboard
|
||||
@@ -36,7 +36,7 @@ export default function Breadcrumbs({ items }: BreadcrumbsProps) {
|
||||
{item.href && !isLast ? (
|
||||
<Link
|
||||
to={item.href}
|
||||
className="transition hover:text-[#33578D]"
|
||||
className="transition hover:text-[#10B981]"
|
||||
>
|
||||
{item.label}
|
||||
</Link>
|
||||
|
||||
@@ -10,7 +10,7 @@ function Input({ className, type, ...props }: React.ComponentProps<"input">) {
|
||||
className={cn(
|
||||
"flex h-10 w-full min-w-0 rounded-md border border-slate-200 bg-white px-3 py-1 text-sm text-slate-700 shadow-xs outline-none transition placeholder:text-slate-400 file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50",
|
||||
"hover:border-slate-300",
|
||||
"focus:border-[#33578D]/50 focus:ring-2 focus:ring-[#33578D]/20",
|
||||
"focus:border-[#10B981]/50 focus:ring-2 focus:ring-[#10B981]/20",
|
||||
"aria-invalid:border-red-500 aria-invalid:ring-2 aria-invalid:ring-red-500/20",
|
||||
className,
|
||||
)}
|
||||
|
||||
@@ -9,7 +9,7 @@ function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
|
||||
className={cn(
|
||||
"field-sizing-content flex min-h-16 w-full rounded-md border border-slate-200 bg-white px-3 py-2 text-sm text-slate-700 shadow-xs outline-none transition placeholder:text-slate-400 disabled:cursor-not-allowed disabled:opacity-50",
|
||||
"hover:border-slate-300",
|
||||
"focus:border-[#33578D]/50 focus:ring-2 focus:ring-[#33578D]/20",
|
||||
"focus:border-[#10B981]/50 focus:ring-2 focus:ring-[#10B981]/20",
|
||||
"aria-invalid:border-red-500 aria-invalid:ring-2 aria-invalid:ring-red-500/20",
|
||||
className,
|
||||
)}
|
||||
|
||||
@@ -72,14 +72,14 @@ export default function DropdownSettingsPage() {
|
||||
value={query}
|
||||
onChange={(e) => setQuery(e.target.value)}
|
||||
placeholder="Search by code, label, description..."
|
||||
className="h-10 w-full rounded-2xl border border-slate-200 bg-white pl-10 pr-4 text-sm text-slate-700 outline-none transition placeholder:text-slate-400 focus:border-[#33578D]/50 focus:ring-2 focus:ring-[#33578D]/20"
|
||||
className="h-10 w-full rounded-2xl border border-slate-200 bg-white pl-10 pr-4 text-sm text-slate-700 outline-none transition placeholder:text-slate-400 focus:border-[#10B981]/50 focus:ring-2 focus:ring-[#10B981]/20"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<EditDropdownSettingDialog mode="create">
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex items-center justify-center gap-2 rounded-2xl bg-[#33578D] px-4 py-2 text-sm font-medium text-white transition hover:bg-[#33578D]/90"
|
||||
className="inline-flex items-center justify-center gap-2 rounded-2xl bg-[#10B981] px-4 py-2 text-sm font-medium text-white transition hover:bg-[#10B981]/90"
|
||||
>
|
||||
<Plus className="h-4 w-4" />
|
||||
New Setting
|
||||
@@ -124,7 +124,7 @@ export default function DropdownSettingsPage() {
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<button className="inline-flex items-center gap-2 rounded-2xl border border-slate-200 px-4 py-2 text-sm font-medium text-slate-700 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D]">
|
||||
<button className="inline-flex items-center gap-2 rounded-2xl border border-slate-200 px-4 py-2 text-sm font-medium text-slate-700 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981]">
|
||||
<Filter className="h-4 w-4" />
|
||||
Filter
|
||||
</button>
|
||||
@@ -157,11 +157,11 @@ export default function DropdownSettingsPage() {
|
||||
filtered.map((setting) => (
|
||||
<tr
|
||||
key={setting.id}
|
||||
className="border-t border-slate-100 transition hover:bg-[#33578D]/5"
|
||||
className="border-t border-slate-100 transition hover:bg-[#10B981]/5"
|
||||
>
|
||||
<td className="px-6 py-4">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-[#33578D]/10 text-[#33578D]">
|
||||
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-[#10B981] text-white">
|
||||
<Settings className="h-5 w-5" />
|
||||
</div>
|
||||
<div>
|
||||
@@ -183,7 +183,7 @@ export default function DropdownSettingsPage() {
|
||||
|
||||
<td className="px-6 py-4">
|
||||
<div className="flex items-center gap-2 text-sm text-slate-700">
|
||||
<Boxes className="h-4 w-4 text-[#33578D]" />
|
||||
<Boxes className="h-4 w-4 text-[#10B981]" />
|
||||
<span className="font-medium">
|
||||
{setting.children.length}
|
||||
</span>
|
||||
@@ -214,7 +214,7 @@ export default function DropdownSettingsPage() {
|
||||
(setting.meta?.permissions ?? []).map((p) => (
|
||||
<span
|
||||
key={p}
|
||||
className="inline-flex items-center gap-1 rounded-full bg-[#33578D]/10 px-2 py-0.5 text-xs font-medium text-[#33578D]"
|
||||
className="inline-flex items-center gap-1 rounded-full bg-[#10B981]/10 px-2 py-0.5 text-xs font-medium text-[#10B981]"
|
||||
>
|
||||
<Shield className="h-3 w-3" />
|
||||
{p}
|
||||
@@ -229,7 +229,7 @@ export default function DropdownSettingsPage() {
|
||||
<ManageDropdownOptionsDialog setting={setting}>
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex items-center gap-1 rounded-xl border border-slate-200 px-3 py-1.5 text-xs font-medium text-slate-600 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D]"
|
||||
className="inline-flex items-center gap-1 rounded-xl border border-slate-200 px-3 py-1.5 text-xs font-medium text-slate-600 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981]"
|
||||
>
|
||||
<CheckCircle2 className="h-3.5 w-3.5" />
|
||||
Options
|
||||
@@ -242,7 +242,7 @@ export default function DropdownSettingsPage() {
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
className="rounded-xl border border-slate-200 p-2 text-slate-600 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D]"
|
||||
className="rounded-xl border border-slate-200 p-2 text-slate-600 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981]"
|
||||
>
|
||||
<Pencil className="h-4 w-4" />
|
||||
</button>
|
||||
@@ -285,7 +285,7 @@ function BehaviorChip({
|
||||
className={
|
||||
muted
|
||||
? "rounded-full bg-slate-100 px-2 py-0.5 text-xs font-medium text-slate-600"
|
||||
: "rounded-full bg-[#33578D]/10 px-2 py-0.5 text-xs font-medium text-[#33578D]"
|
||||
: "rounded-full bg-[#10B981]/10 px-2 py-0.5 text-xs font-medium text-[#10B981]"
|
||||
}
|
||||
>
|
||||
{label}
|
||||
@@ -303,13 +303,13 @@ function StatCard({
|
||||
icon: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<div className="rounded-3xl bg-white p-6 shadow-sm transition hover:shadow-md hover:ring-1 hover:ring-[#33578D]/20">
|
||||
<div className="rounded-3xl bg-white p-6 shadow-sm transition hover:shadow-md hover:ring-1 hover:ring-[#10B981]/20">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm text-slate-500">{title}</p>
|
||||
<h3 className="mt-2 text-3xl font-bold text-slate-900">{value}</h3>
|
||||
</div>
|
||||
<div className="flex h-12 w-12 items-center justify-center rounded-2xl bg-[#33578D]/10 text-[#33578D]">
|
||||
<div className="flex h-12 w-12 items-center justify-center rounded-2xl bg-[#10B981] text-white">
|
||||
{icon}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -97,7 +97,7 @@ export default function EditDropdownSettingDialog({
|
||||
<Input
|
||||
type="text"
|
||||
defaultValue={setting?.meta?.color ?? ""}
|
||||
placeholder="#33578D"
|
||||
placeholder="#10B981"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -144,7 +144,7 @@ export default function EditDropdownSettingDialog({
|
||||
|
||||
<div className="flex justify-end gap-3">
|
||||
<Button variant="outline">Cancel</Button>
|
||||
<Button className="bg-[#33578D] text-white hover:bg-[#33578D]/90">
|
||||
<Button className="bg-[#10B981] text-white hover:bg-[#10B981]/90">
|
||||
{isEdit ? "Save Changes" : "Create Setting"}
|
||||
</Button>
|
||||
</div>
|
||||
@@ -168,15 +168,15 @@ function ToggleChip({
|
||||
<label
|
||||
className={
|
||||
checked
|
||||
? "flex cursor-pointer items-start gap-2 rounded-2xl border border-[#33578D]/40 bg-[#33578D]/10 px-3 py-2 text-sm"
|
||||
: "flex cursor-pointer items-start gap-2 rounded-2xl border border-slate-200 bg-white px-3 py-2 text-sm transition hover:border-[#33578D]/30 hover:bg-[#33578D]/5"
|
||||
? "flex cursor-pointer items-start gap-2 rounded-2xl border border-[#10B981]/40 bg-[#10B981]/10 px-3 py-2 text-sm"
|
||||
: "flex cursor-pointer items-start gap-2 rounded-2xl border border-slate-200 bg-white px-3 py-2 text-sm transition hover:border-[#10B981]/30 hover:bg-[#10B981]/5"
|
||||
}
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={checked}
|
||||
onChange={(e) => onChange(e.target.checked)}
|
||||
className="mt-0.5 h-4 w-4 rounded border-slate-300 text-[#33578D] focus:ring-[#33578D]/20"
|
||||
className="mt-0.5 h-4 w-4 rounded border-slate-300 text-[#10B981] focus:ring-[#10B981]/20"
|
||||
/>
|
||||
<div>
|
||||
<p className="font-medium text-slate-900">{label}</p>
|
||||
|
||||
@@ -100,7 +100,7 @@ export default function ManageDropdownOptionsDialog({
|
||||
<button
|
||||
type="button"
|
||||
onClick={add}
|
||||
className="inline-flex items-center gap-1.5 rounded-xl bg-[#33578D] px-3 py-1.5 text-xs font-medium text-white transition hover:bg-[#33578D]/90"
|
||||
className="inline-flex items-center gap-1.5 rounded-xl bg-[#10B981] px-3 py-1.5 text-xs font-medium text-white transition hover:bg-[#10B981]/90"
|
||||
>
|
||||
<Plus className="h-3.5 w-3.5" />
|
||||
Add Option
|
||||
@@ -126,7 +126,7 @@ export default function ManageDropdownOptionsDialog({
|
||||
onClick={() => move(i, -1)}
|
||||
aria-label="Move up"
|
||||
disabled={i === 0}
|
||||
className="text-[10px] leading-none text-slate-400 transition hover:text-[#33578D] disabled:opacity-30"
|
||||
className="text-[10px] leading-none text-slate-400 transition hover:text-[#10B981] disabled:opacity-30"
|
||||
>
|
||||
▲
|
||||
</button>
|
||||
@@ -135,7 +135,7 @@ export default function ManageDropdownOptionsDialog({
|
||||
onClick={() => move(i, 1)}
|
||||
aria-label="Move down"
|
||||
disabled={i === options.length - 1}
|
||||
className="text-[10px] leading-none text-slate-400 transition hover:text-[#33578D] disabled:opacity-30"
|
||||
className="text-[10px] leading-none text-slate-400 transition hover:text-[#10B981] disabled:opacity-30"
|
||||
>
|
||||
▼
|
||||
</button>
|
||||
@@ -199,7 +199,7 @@ export default function ManageDropdownOptionsDialog({
|
||||
onChange={(e) =>
|
||||
update(i, { disabled: e.target.checked })
|
||||
}
|
||||
className="h-3.5 w-3.5 rounded border-slate-300 text-[#33578D] focus:ring-[#33578D]/20"
|
||||
className="h-3.5 w-3.5 rounded border-slate-300 text-[#10B981] focus:ring-[#10B981]/20"
|
||||
/>
|
||||
Off
|
||||
</label>
|
||||
@@ -220,7 +220,7 @@ export default function ManageDropdownOptionsDialog({
|
||||
|
||||
<div className="flex justify-end gap-3 border-t border-slate-100 pt-3">
|
||||
<Button variant="outline">Cancel</Button>
|
||||
<Button className="bg-[#33578D] text-white hover:bg-[#33578D]/90">
|
||||
<Button className="bg-[#10B981] text-white hover:bg-[#10B981]/90">
|
||||
Save Options
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -104,14 +104,14 @@ export default function BillingPage() {
|
||||
setPage(1);
|
||||
}}
|
||||
placeholder="Search invoices..."
|
||||
className="h-10 w-full rounded-2xl border border-slate-200 bg-white pl-10 pr-4 text-sm text-slate-700 outline-none transition placeholder:text-slate-400 focus:border-[#33578D]/50 focus:ring-2 focus:ring-[#33578D]/20"
|
||||
className="h-10 w-full rounded-2xl border border-slate-200 bg-white pl-10 pr-4 text-sm text-slate-700 outline-none transition placeholder:text-slate-400 focus:border-[#10B981]/50 focus:ring-2 focus:ring-[#10B981]/20"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<NewInvoicePage>
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex items-center justify-center gap-2 rounded-2xl bg-[#33578D] px-4 py-2 text-sm font-medium text-white transition hover:bg-[#33578D]/90"
|
||||
className="inline-flex items-center justify-center gap-2 rounded-2xl bg-[#10B981] px-4 py-2 text-sm font-medium text-white transition hover:bg-[#10B981]/90"
|
||||
>
|
||||
<Plus className="h-4 w-4" />
|
||||
New Invoice
|
||||
@@ -161,8 +161,8 @@ export default function BillingPage() {
|
||||
}}
|
||||
className={
|
||||
isActive
|
||||
? "inline-flex items-center gap-2 rounded-2xl bg-[#33578D] px-4 py-2 text-sm font-medium text-white"
|
||||
: "inline-flex items-center gap-2 rounded-2xl px-4 py-2 text-sm font-medium text-slate-600 transition hover:bg-[#33578D]/10 hover:text-[#33578D]"
|
||||
? "inline-flex items-center gap-2 rounded-2xl bg-[#10B981] px-4 py-2 text-sm font-medium text-white"
|
||||
: "inline-flex items-center gap-2 rounded-2xl px-4 py-2 text-sm font-medium text-slate-600 transition hover:bg-[#10B981]/10 hover:text-[#10B981]"
|
||||
}
|
||||
>
|
||||
{f}
|
||||
@@ -193,7 +193,7 @@ export default function BillingPage() {
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<button className="inline-flex items-center gap-2 rounded-2xl border border-slate-200 px-4 py-2 text-sm font-medium text-slate-700 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D]">
|
||||
<button className="inline-flex items-center gap-2 rounded-2xl border border-slate-200 px-4 py-2 text-sm font-medium text-slate-700 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981]">
|
||||
<Filter className="h-4 w-4" />
|
||||
Filter
|
||||
</button>
|
||||
@@ -227,11 +227,11 @@ export default function BillingPage() {
|
||||
paginated.map((invoice) => (
|
||||
<tr
|
||||
key={invoice.id}
|
||||
className="border-t border-slate-100 transition hover:bg-[#33578D]/5"
|
||||
className="border-t border-slate-100 transition hover:bg-[#10B981]/5"
|
||||
>
|
||||
<td className="px-6 py-4">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-[#33578D]/10 text-[#33578D]">
|
||||
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-[#10B981] text-white">
|
||||
<Receipt className="h-5 w-5" />
|
||||
</div>
|
||||
<div>
|
||||
@@ -270,7 +270,7 @@ export default function BillingPage() {
|
||||
<button
|
||||
type="button"
|
||||
aria-label="Download invoice"
|
||||
className="rounded-xl border border-slate-200 p-2 text-slate-600 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D]"
|
||||
className="rounded-xl border border-slate-200 p-2 text-slate-600 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981]"
|
||||
>
|
||||
<Download className="h-4 w-4" />
|
||||
</button>
|
||||
@@ -291,7 +291,7 @@ export default function BillingPage() {
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
className="rounded-xl border border-slate-200 p-2 text-slate-600 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D]"
|
||||
className="rounded-xl border border-slate-200 p-2 text-slate-600 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981]"
|
||||
>
|
||||
<Pencil className="h-4 w-4" />
|
||||
</button>
|
||||
@@ -364,7 +364,7 @@ function Pagination({
|
||||
id="invoice-page-size"
|
||||
value={pageSize}
|
||||
onChange={(e) => onPageSizeChange(Number(e.target.value))}
|
||||
className="h-9 rounded-xl border border-slate-200 bg-white px-3 text-sm text-slate-700 outline-none transition focus:border-[#33578D]/50 focus:ring-2 focus:ring-[#33578D]/20"
|
||||
className="h-9 rounded-xl border border-slate-200 bg-white px-3 text-sm text-slate-700 outline-none transition focus:border-[#10B981]/50 focus:ring-2 focus:ring-[#10B981]/20"
|
||||
>
|
||||
{PAGE_SIZE_OPTIONS.map((size) => (
|
||||
<option key={size} value={size}>
|
||||
@@ -382,7 +382,7 @@ function Pagination({
|
||||
type="button"
|
||||
onClick={() => onPageChange(page - 1)}
|
||||
disabled={page <= 1}
|
||||
className="inline-flex h-9 items-center gap-1 rounded-xl border border-slate-200 px-3 text-sm font-medium text-slate-700 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D] disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent disabled:hover:text-slate-700"
|
||||
className="inline-flex h-9 items-center gap-1 rounded-xl border border-slate-200 px-3 text-sm font-medium text-slate-700 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981] disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent disabled:hover:text-slate-700"
|
||||
>
|
||||
<ChevronLeft className="h-4 w-4" />
|
||||
Prev
|
||||
@@ -398,8 +398,8 @@ function Pagination({
|
||||
aria-current={isActive ? "page" : undefined}
|
||||
className={
|
||||
isActive
|
||||
? "h-9 w-9 rounded-xl bg-[#33578D] text-sm font-medium text-white"
|
||||
: "h-9 w-9 rounded-xl border border-slate-200 text-sm font-medium text-slate-700 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D]"
|
||||
? "h-9 w-9 rounded-xl bg-[#10B981] text-sm font-medium text-white"
|
||||
: "h-9 w-9 rounded-xl border border-slate-200 text-sm font-medium text-slate-700 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981]"
|
||||
}
|
||||
>
|
||||
{p}
|
||||
@@ -411,7 +411,7 @@ function Pagination({
|
||||
type="button"
|
||||
onClick={() => onPageChange(page + 1)}
|
||||
disabled={page >= totalPages}
|
||||
className="inline-flex h-9 items-center gap-1 rounded-xl border border-slate-200 px-3 text-sm font-medium text-slate-700 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D] disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent disabled:hover:text-slate-700"
|
||||
className="inline-flex h-9 items-center gap-1 rounded-xl border border-slate-200 px-3 text-sm font-medium text-slate-700 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981] disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent disabled:hover:text-slate-700"
|
||||
>
|
||||
Next
|
||||
<ChevronRight className="h-4 w-4" />
|
||||
@@ -435,10 +435,10 @@ function StatCard({
|
||||
const iconWrap =
|
||||
tone === "danger"
|
||||
? "bg-red-100 text-red-600"
|
||||
: "bg-[#33578D]/10 text-[#33578D]";
|
||||
: "bg-[#10B981] text-white";
|
||||
|
||||
return (
|
||||
<div className="rounded-3xl bg-white p-6 shadow-sm transition hover:shadow-md hover:ring-1 hover:ring-[#33578D]/20">
|
||||
<div className="rounded-3xl bg-white p-6 shadow-sm transition hover:shadow-md hover:ring-1 hover:ring-[#10B981]/20">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm text-slate-500">{title}</p>
|
||||
|
||||
@@ -37,7 +37,7 @@ export interface NewInvoicePageProps {
|
||||
}
|
||||
|
||||
const selectClass =
|
||||
"flex h-10 w-full rounded-md border border-slate-200 bg-white px-3 py-2 text-sm text-slate-700 shadow-xs outline-none transition hover:border-slate-300 focus:border-[#33578D]/50 focus:ring-2 focus:ring-[#33578D]/20";
|
||||
"flex h-10 w-full rounded-md border border-slate-200 bg-white px-3 py-2 text-sm text-slate-700 shadow-xs outline-none transition hover:border-slate-300 focus:border-[#10B981]/50 focus:ring-2 focus:ring-[#10B981]/20";
|
||||
|
||||
export default function NewInvoicePage({
|
||||
mode = "create",
|
||||
@@ -192,7 +192,7 @@ export default function NewInvoicePage({
|
||||
|
||||
<div className="flex justify-end gap-3">
|
||||
<Button variant="outline">Cancel</Button>
|
||||
<Button className="bg-[#33578D] text-white hover:bg-[#33578D]/90">
|
||||
<Button className="bg-[#10B981] text-white hover:bg-[#10B981]/90">
|
||||
{submitLabel}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -42,7 +42,7 @@ export default function BookingDetailPage() {
|
||||
</p>
|
||||
<Link
|
||||
to="/bookings"
|
||||
className="mt-6 inline-flex items-center gap-2 rounded-2xl bg-[#33578D] px-4 py-2 text-sm font-medium text-white transition hover:bg-[#33578D]/90"
|
||||
className="mt-6 inline-flex items-center gap-2 rounded-2xl bg-[#10B981] px-4 py-2 text-sm font-medium text-white transition hover:bg-[#10B981]/90"
|
||||
>
|
||||
<ArrowLeft className="h-4 w-4" />
|
||||
Back to Bookings
|
||||
@@ -67,7 +67,7 @@ export default function BookingDetailPage() {
|
||||
<div className="rounded-3xl bg-white p-6 shadow-sm">
|
||||
<div className="flex flex-col gap-4 md:flex-row md:items-center md:justify-between">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="flex h-16 w-16 items-center justify-center rounded-2xl bg-[#33578D]/10 text-[#33578D]">
|
||||
<div className="flex h-16 w-16 items-center justify-center rounded-2xl bg-[#10B981] text-white">
|
||||
<Package className="h-8 w-8" />
|
||||
</div>
|
||||
<div>
|
||||
@@ -105,7 +105,7 @@ export default function BookingDetailPage() {
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex items-center gap-2 rounded-2xl bg-[#33578D] px-4 py-2 text-sm font-medium text-white transition hover:bg-[#33578D]/90"
|
||||
className="inline-flex items-center gap-2 rounded-2xl bg-[#10B981] px-4 py-2 text-sm font-medium text-white transition hover:bg-[#10B981]/90"
|
||||
>
|
||||
Edit Booking
|
||||
</button>
|
||||
@@ -135,7 +135,7 @@ export default function BookingDetailPage() {
|
||||
station={booking.originStation}
|
||||
icon={<MapPin className="h-5 w-5" />}
|
||||
/>
|
||||
<div className="flex items-center gap-2 text-[#33578D]">
|
||||
<div className="flex items-center gap-2 text-[#10B981]">
|
||||
<Train className="h-5 w-5" />
|
||||
<ArrowRight className="h-5 w-5" />
|
||||
</div>
|
||||
@@ -151,11 +151,11 @@ export default function BookingDetailPage() {
|
||||
{booking.transportMode === "Multimodal" && booking.legs && booking.legs.length > 0 ? (
|
||||
<div className="rounded-3xl bg-white p-6 shadow-sm">
|
||||
<div className="mb-4 flex items-center gap-2">
|
||||
<Train className="h-5 w-5 text-[#33578D]" />
|
||||
<Train className="h-5 w-5 text-[#10B981]" />
|
||||
<h2 className="text-lg font-semibold text-slate-900">
|
||||
Transport Legs
|
||||
</h2>
|
||||
<span className="rounded-full bg-[#33578D]/10 px-2 py-0.5 text-xs font-medium text-[#33578D]">
|
||||
<span className="rounded-full bg-[#10B981]/10 px-2 py-0.5 text-xs font-medium text-[#10B981]">
|
||||
{booking.legs.length} legs
|
||||
</span>
|
||||
</div>
|
||||
@@ -163,10 +163,10 @@ export default function BookingDetailPage() {
|
||||
{booking.legs.map((leg, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="flex flex-col gap-3 rounded-2xl border border-slate-200 bg-[#33578D]/5 p-4 md:flex-row md:items-center md:justify-between"
|
||||
className="flex flex-col gap-3 rounded-2xl border border-slate-200 bg-[#10B981]/5 p-4 md:flex-row md:items-center md:justify-between"
|
||||
>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex h-10 w-10 items-center justify-center rounded-xl bg-[#33578D] text-sm font-bold text-white">
|
||||
<div className="flex h-10 w-10 items-center justify-center rounded-xl bg-[#10B981] text-sm font-bold text-white">
|
||||
{i + 1}
|
||||
</div>
|
||||
<div>
|
||||
@@ -175,7 +175,7 @@ export default function BookingDetailPage() {
|
||||
</p>
|
||||
<p className="font-semibold text-slate-900">
|
||||
{leg.from || "—"}
|
||||
<ArrowRight className="mx-2 inline h-4 w-4 text-[#33578D]" />
|
||||
<ArrowRight className="mx-2 inline h-4 w-4 text-[#10B981]" />
|
||||
{leg.to || "—"}
|
||||
</p>
|
||||
</div>
|
||||
@@ -231,14 +231,14 @@ export default function BookingDetailPage() {
|
||||
|
||||
<DetailCard title="Cargo Description">
|
||||
<div className="flex items-start gap-3 text-sm text-slate-700">
|
||||
<Package className="mt-0.5 h-4 w-4 text-[#33578D]" />
|
||||
<Package className="mt-0.5 h-4 w-4 text-[#10B981]" />
|
||||
<p className="leading-relaxed">{booking.cargoDescription}</p>
|
||||
</div>
|
||||
</DetailCard>
|
||||
|
||||
<DetailCard title="Special Instructions">
|
||||
<div className="flex items-start gap-3 text-sm text-slate-700">
|
||||
<StickyNote className="mt-0.5 h-4 w-4 text-[#33578D]" />
|
||||
<StickyNote className="mt-0.5 h-4 w-4 text-[#10B981]" />
|
||||
<p className="leading-relaxed">{booking.specialInstructions}</p>
|
||||
</div>
|
||||
</DetailCard>
|
||||
@@ -259,7 +259,7 @@ function RouteEndpoint({
|
||||
}) {
|
||||
return (
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex h-12 w-12 items-center justify-center rounded-2xl bg-[#33578D]/10 text-[#33578D]">
|
||||
<div className="flex h-12 w-12 items-center justify-center rounded-2xl bg-[#10B981] text-white">
|
||||
{icon}
|
||||
</div>
|
||||
<div>
|
||||
@@ -298,7 +298,7 @@ function DetailRow({
|
||||
}) {
|
||||
return (
|
||||
<div className="flex items-start gap-3">
|
||||
<div className="mt-0.5 text-[#33578D]">{icon}</div>
|
||||
<div className="mt-0.5 text-[#10B981]">{icon}</div>
|
||||
<div className="flex-1">
|
||||
<p className="text-xs font-medium text-slate-500">{label}</p>
|
||||
<p className="mt-0.5 text-sm text-slate-900">{value}</p>
|
||||
|
||||
@@ -58,14 +58,14 @@ export default function BookingsPage() {
|
||||
<input
|
||||
type="search"
|
||||
placeholder="Search bookings..."
|
||||
className="h-10 w-full rounded-2xl border border-slate-200 bg-white pl-10 pr-4 text-sm text-slate-700 outline-none transition placeholder:text-slate-400 focus:border-[#33578D]/50 focus:ring-2 focus:ring-[#33578D]/20"
|
||||
className="h-10 w-full rounded-2xl border border-slate-200 bg-white pl-10 pr-4 text-sm text-slate-700 outline-none transition placeholder:text-slate-400 focus:border-[#10B981]/50 focus:ring-2 focus:ring-[#10B981]/20"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<NewBookingPage>
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex items-center justify-center gap-2 rounded-2xl bg-[#33578D] px-4 py-2 text-sm font-medium text-white transition hover:bg-[#33578D]/90"
|
||||
className="inline-flex items-center justify-center gap-2 rounded-2xl bg-[#10B981] px-4 py-2 text-sm font-medium text-white transition hover:bg-[#10B981]/90"
|
||||
>
|
||||
<Plus className="h-4 w-4" />
|
||||
New Booking
|
||||
@@ -109,7 +109,7 @@ export default function BookingsPage() {
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<button className="inline-flex items-center gap-2 rounded-2xl border border-slate-200 px-4 py-2 text-sm font-medium text-slate-700 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D]">
|
||||
<button className="inline-flex items-center gap-2 rounded-2xl border border-slate-200 px-4 py-2 text-sm font-medium text-slate-700 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981]">
|
||||
<Filter className="h-4 w-4" />
|
||||
Filter
|
||||
</button>
|
||||
@@ -132,11 +132,11 @@ export default function BookingsPage() {
|
||||
{paginated.map((booking) => (
|
||||
<tr
|
||||
key={booking.id}
|
||||
className="border-t border-slate-100 transition hover:bg-[#33578D]/5"
|
||||
className="border-t border-slate-100 transition hover:bg-[#10B981]/5"
|
||||
>
|
||||
<td className="px-6 py-4">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-[#33578D]/10 text-[#33578D]">
|
||||
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-[#10B981] text-white">
|
||||
<Package className="h-5 w-5" />
|
||||
</div>
|
||||
<div>
|
||||
@@ -180,7 +180,7 @@ export default function BookingsPage() {
|
||||
<div className="flex justify-end gap-2">
|
||||
<Link
|
||||
to={`/bookings/${booking.id}`}
|
||||
className="rounded-xl border border-slate-200 p-2 text-slate-600 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D]"
|
||||
className="rounded-xl border border-slate-200 p-2 text-slate-600 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981]"
|
||||
>
|
||||
<Eye className="h-4 w-4" />
|
||||
</Link>
|
||||
@@ -205,7 +205,7 @@ export default function BookingsPage() {
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
className="rounded-xl border border-slate-200 p-2 text-slate-600 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D]"
|
||||
className="rounded-xl border border-slate-200 p-2 text-slate-600 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981]"
|
||||
>
|
||||
<Pencil className="h-4 w-4" />
|
||||
</button>
|
||||
@@ -279,7 +279,7 @@ function Pagination({
|
||||
id="booking-page-size"
|
||||
value={pageSize}
|
||||
onChange={(e) => onPageSizeChange(Number(e.target.value))}
|
||||
className="h-9 rounded-xl border border-slate-200 bg-white px-3 text-sm text-slate-700 outline-none transition focus:border-[#33578D]/50 focus:ring-2 focus:ring-[#33578D]/20"
|
||||
className="h-9 rounded-xl border border-slate-200 bg-white px-3 text-sm text-slate-700 outline-none transition focus:border-[#10B981]/50 focus:ring-2 focus:ring-[#10B981]/20"
|
||||
>
|
||||
{PAGE_SIZE_OPTIONS.map((size) => (
|
||||
<option key={size} value={size}>
|
||||
@@ -297,7 +297,7 @@ function Pagination({
|
||||
type="button"
|
||||
onClick={() => onPageChange(page - 1)}
|
||||
disabled={page <= 1}
|
||||
className="inline-flex h-9 items-center gap-1 rounded-xl border border-slate-200 px-3 text-sm font-medium text-slate-700 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D] disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent disabled:hover:text-slate-700"
|
||||
className="inline-flex h-9 items-center gap-1 rounded-xl border border-slate-200 px-3 text-sm font-medium text-slate-700 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981] disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent disabled:hover:text-slate-700"
|
||||
>
|
||||
<ChevronLeft className="h-4 w-4" />
|
||||
Prev
|
||||
@@ -313,8 +313,8 @@ function Pagination({
|
||||
aria-current={isActive ? "page" : undefined}
|
||||
className={
|
||||
isActive
|
||||
? "h-9 w-9 rounded-xl bg-[#33578D] text-sm font-medium text-white"
|
||||
: "h-9 w-9 rounded-xl border border-slate-200 text-sm font-medium text-slate-700 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D]"
|
||||
? "h-9 w-9 rounded-xl bg-[#10B981] text-sm font-medium text-white"
|
||||
: "h-9 w-9 rounded-xl border border-slate-200 text-sm font-medium text-slate-700 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981]"
|
||||
}
|
||||
>
|
||||
{p}
|
||||
@@ -326,7 +326,7 @@ function Pagination({
|
||||
type="button"
|
||||
onClick={() => onPageChange(page + 1)}
|
||||
disabled={page >= totalPages}
|
||||
className="inline-flex h-9 items-center gap-1 rounded-xl border border-slate-200 px-3 text-sm font-medium text-slate-700 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D] disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent disabled:hover:text-slate-700"
|
||||
className="inline-flex h-9 items-center gap-1 rounded-xl border border-slate-200 px-3 text-sm font-medium text-slate-700 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981] disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent disabled:hover:text-slate-700"
|
||||
>
|
||||
Next
|
||||
<ChevronRight className="h-4 w-4" />
|
||||
@@ -346,13 +346,13 @@ function StatCard({
|
||||
icon: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<div className="rounded-3xl bg-white p-6 shadow-sm transition hover:shadow-md hover:ring-1 hover:ring-[#33578D]/20">
|
||||
<div className="rounded-3xl bg-white p-6 shadow-sm transition hover:shadow-md hover:ring-1 hover:ring-[#10B981]/20">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm text-slate-500">{title}</p>
|
||||
<h3 className="mt-2 text-3xl font-bold text-slate-900">{value}</h3>
|
||||
</div>
|
||||
<div className="flex h-12 w-12 items-center justify-center rounded-2xl bg-[#33578D]/10 text-[#33578D]">
|
||||
<div className="flex h-12 w-12 items-center justify-center rounded-2xl bg-[#10B981] text-white">
|
||||
{icon}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -47,7 +47,7 @@ export interface NewBookingPageProps {
|
||||
}
|
||||
|
||||
const selectClass =
|
||||
"flex h-10 w-full rounded-md border border-slate-200 bg-white px-3 py-2 text-sm text-slate-700 shadow-xs outline-none transition hover:border-slate-300 focus:border-[#33578D]/50 focus:ring-2 focus:ring-[#33578D]/20";
|
||||
"flex h-10 w-full rounded-md border border-slate-200 bg-white px-3 py-2 text-sm text-slate-700 shadow-xs outline-none transition hover:border-slate-300 focus:border-[#10B981]/50 focus:ring-2 focus:ring-[#10B981]/20";
|
||||
|
||||
const emptyLeg: TransportLeg = { mode: "Rail", from: "", to: "" };
|
||||
|
||||
@@ -188,7 +188,7 @@ export default function NewBookingPage({
|
||||
{/* Multimodal Transport Legs */}
|
||||
{transportMode === "Multimodal" ? (
|
||||
<div className="md:col-span-2">
|
||||
<div className="rounded-2xl border border-slate-200 bg-[#33578D]/5 p-4">
|
||||
<div className="rounded-2xl border border-slate-200 bg-[#10B981]/5 p-4">
|
||||
<div className="mb-3 flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm font-semibold text-slate-900">
|
||||
@@ -201,7 +201,7 @@ export default function NewBookingPage({
|
||||
<button
|
||||
type="button"
|
||||
onClick={addLeg}
|
||||
className="inline-flex items-center gap-1.5 rounded-xl bg-[#33578D] px-3 py-1.5 text-xs font-medium text-white transition hover:bg-[#33578D]/90"
|
||||
className="inline-flex items-center gap-1.5 rounded-xl bg-[#10B981] px-3 py-1.5 text-xs font-medium text-white transition hover:bg-[#10B981]/90"
|
||||
>
|
||||
<Plus className="h-3.5 w-3.5" />
|
||||
Add Leg
|
||||
@@ -215,7 +215,7 @@ export default function NewBookingPage({
|
||||
className="rounded-xl border border-slate-200 bg-white p-3"
|
||||
>
|
||||
<div className="mb-2 flex items-center justify-between">
|
||||
<span className="text-xs font-semibold uppercase tracking-wide text-[#33578D]">
|
||||
<span className="text-xs font-semibold uppercase tracking-wide text-[#10B981]">
|
||||
Leg {i + 1}
|
||||
</span>
|
||||
{legs.length > 1 ? (
|
||||
@@ -356,7 +356,7 @@ export default function NewBookingPage({
|
||||
|
||||
<div className="flex justify-end gap-3">
|
||||
<Button variant="outline">Cancel</Button>
|
||||
<Button className="bg-[#33578D] text-white hover:bg-[#33578D]/90">
|
||||
<Button className="bg-[#10B981] text-white hover:bg-[#10B981]/90">
|
||||
{submitLabel}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -47,7 +47,7 @@ export default function ConsignmentDetailPage() {
|
||||
</p>
|
||||
<Link
|
||||
to="/consignments"
|
||||
className="mt-6 inline-flex items-center gap-2 rounded-2xl bg-[#33578D] px-4 py-2 text-sm font-medium text-white transition hover:bg-[#33578D]/90"
|
||||
className="mt-6 inline-flex items-center gap-2 rounded-2xl bg-[#10B981] px-4 py-2 text-sm font-medium text-white transition hover:bg-[#10B981]/90"
|
||||
>
|
||||
<ArrowLeft className="h-4 w-4" />
|
||||
Back to Consignments
|
||||
@@ -72,7 +72,7 @@ export default function ConsignmentDetailPage() {
|
||||
<div className="rounded-3xl bg-white p-6 shadow-sm">
|
||||
<div className="flex flex-col gap-4 md:flex-row md:items-center md:justify-between">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="flex h-16 w-16 items-center justify-center rounded-2xl bg-[#33578D]/10 text-[#33578D]">
|
||||
<div className="flex h-16 w-16 items-center justify-center rounded-2xl bg-[#10B981] text-white">
|
||||
<Package className="h-8 w-8" />
|
||||
</div>
|
||||
<div>
|
||||
@@ -115,7 +115,7 @@ export default function ConsignmentDetailPage() {
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex items-center gap-2 rounded-2xl bg-[#33578D] px-4 py-2 text-sm font-medium text-white transition hover:bg-[#33578D]/90"
|
||||
className="inline-flex items-center gap-2 rounded-2xl bg-[#10B981] px-4 py-2 text-sm font-medium text-white transition hover:bg-[#10B981]/90"
|
||||
>
|
||||
Edit Consignment
|
||||
</button>
|
||||
@@ -144,7 +144,7 @@ export default function ConsignmentDetailPage() {
|
||||
label="Origin"
|
||||
station={consignment.originStation}
|
||||
/>
|
||||
<ArrowRight className="h-5 w-5 text-[#33578D]" />
|
||||
<ArrowRight className="h-5 w-5 text-[#10B981]" />
|
||||
<RouteEndpoint
|
||||
label="Destination"
|
||||
station={consignment.destinationStation}
|
||||
@@ -202,14 +202,14 @@ export default function ConsignmentDetailPage() {
|
||||
|
||||
<DetailCard title="Description">
|
||||
<div className="flex items-start gap-3 text-sm text-slate-700">
|
||||
<Package className="mt-0.5 h-4 w-4 text-[#33578D]" />
|
||||
<Package className="mt-0.5 h-4 w-4 text-[#10B981]" />
|
||||
<p className="leading-relaxed">{consignment.description}</p>
|
||||
</div>
|
||||
</DetailCard>
|
||||
|
||||
<DetailCard title="Special Handling">
|
||||
<div className="flex items-start gap-3 text-sm text-slate-700">
|
||||
<StickyNote className="mt-0.5 h-4 w-4 text-[#33578D]" />
|
||||
<StickyNote className="mt-0.5 h-4 w-4 text-[#10B981]" />
|
||||
<p className="leading-relaxed">{consignment.specialHandling}</p>
|
||||
</div>
|
||||
</DetailCard>
|
||||
@@ -228,7 +228,7 @@ function RouteEndpoint({
|
||||
}) {
|
||||
return (
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex h-12 w-12 items-center justify-center rounded-2xl bg-[#33578D]/10 text-[#33578D]">
|
||||
<div className="flex h-12 w-12 items-center justify-center rounded-2xl bg-[#10B981] text-white">
|
||||
<MapPin className="h-5 w-5" />
|
||||
</div>
|
||||
<div>
|
||||
@@ -267,7 +267,7 @@ function DetailRow({
|
||||
}) {
|
||||
return (
|
||||
<div className="flex items-start gap-3">
|
||||
<div className="mt-0.5 text-[#33578D]">{icon}</div>
|
||||
<div className="mt-0.5 text-[#10B981]">{icon}</div>
|
||||
<div className="flex-1">
|
||||
<p className="text-xs font-medium text-slate-500">{label}</p>
|
||||
<p className="mt-0.5 text-sm text-slate-900">{value}</p>
|
||||
|
||||
@@ -104,14 +104,14 @@ export default function ConsignmentsPage() {
|
||||
setPage(1);
|
||||
}}
|
||||
placeholder="Search consignments..."
|
||||
className="h-10 w-full rounded-2xl border border-slate-200 bg-white pl-10 pr-4 text-sm text-slate-700 outline-none transition placeholder:text-slate-400 focus:border-[#33578D]/50 focus:ring-2 focus:ring-[#33578D]/20"
|
||||
className="h-10 w-full rounded-2xl border border-slate-200 bg-white pl-10 pr-4 text-sm text-slate-700 outline-none transition placeholder:text-slate-400 focus:border-[#10B981]/50 focus:ring-2 focus:ring-[#10B981]/20"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<NewConsignmentPage>
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex items-center justify-center gap-2 rounded-2xl bg-[#33578D] px-4 py-2 text-sm font-medium text-white transition hover:bg-[#33578D]/90"
|
||||
className="inline-flex items-center justify-center gap-2 rounded-2xl bg-[#10B981] px-4 py-2 text-sm font-medium text-white transition hover:bg-[#10B981]/90"
|
||||
>
|
||||
<Plus className="h-4 w-4" />
|
||||
New Consignment
|
||||
@@ -164,8 +164,8 @@ export default function ConsignmentsPage() {
|
||||
}}
|
||||
className={
|
||||
isActive
|
||||
? "inline-flex items-center gap-2 rounded-2xl bg-[#33578D] px-4 py-2 text-sm font-medium text-white"
|
||||
: "inline-flex items-center gap-2 rounded-2xl px-4 py-2 text-sm font-medium text-slate-600 transition hover:bg-[#33578D]/10 hover:text-[#33578D]"
|
||||
? "inline-flex items-center gap-2 rounded-2xl bg-[#10B981] px-4 py-2 text-sm font-medium text-white"
|
||||
: "inline-flex items-center gap-2 rounded-2xl px-4 py-2 text-sm font-medium text-slate-600 transition hover:bg-[#10B981]/10 hover:text-[#10B981]"
|
||||
}
|
||||
>
|
||||
{f}
|
||||
@@ -196,7 +196,7 @@ export default function ConsignmentsPage() {
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<button className="inline-flex items-center gap-2 rounded-2xl border border-slate-200 px-4 py-2 text-sm font-medium text-slate-700 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D]">
|
||||
<button className="inline-flex items-center gap-2 rounded-2xl border border-slate-200 px-4 py-2 text-sm font-medium text-slate-700 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981]">
|
||||
<Filter className="h-4 w-4" />
|
||||
Filter
|
||||
</button>
|
||||
@@ -230,11 +230,11 @@ export default function ConsignmentsPage() {
|
||||
paginated.map((consignment) => (
|
||||
<tr
|
||||
key={consignment.id}
|
||||
className="border-t border-slate-100 transition hover:bg-[#33578D]/5"
|
||||
className="border-t border-slate-100 transition hover:bg-[#10B981]/5"
|
||||
>
|
||||
<td className="px-6 py-4">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-[#33578D]/10 text-[#33578D]">
|
||||
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-[#10B981] text-white">
|
||||
<Package className="h-5 w-5" />
|
||||
</div>
|
||||
<div>
|
||||
@@ -292,7 +292,7 @@ export default function ConsignmentsPage() {
|
||||
<div className="flex justify-end gap-2">
|
||||
<Link
|
||||
to={`/consignments/${consignment.id}`}
|
||||
className="rounded-xl border border-slate-200 p-2 text-slate-600 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D]"
|
||||
className="rounded-xl border border-slate-200 p-2 text-slate-600 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981]"
|
||||
>
|
||||
<Eye className="h-4 w-4" />
|
||||
</Link>
|
||||
@@ -316,7 +316,7 @@ export default function ConsignmentsPage() {
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
className="rounded-xl border border-slate-200 p-2 text-slate-600 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D]"
|
||||
className="rounded-xl border border-slate-200 p-2 text-slate-600 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981]"
|
||||
>
|
||||
<Pencil className="h-4 w-4" />
|
||||
</button>
|
||||
@@ -394,7 +394,7 @@ function Pagination({
|
||||
id="consignment-page-size"
|
||||
value={pageSize}
|
||||
onChange={(e) => onPageSizeChange(Number(e.target.value))}
|
||||
className="h-9 rounded-xl border border-slate-200 bg-white px-3 text-sm text-slate-700 outline-none transition focus:border-[#33578D]/50 focus:ring-2 focus:ring-[#33578D]/20"
|
||||
className="h-9 rounded-xl border border-slate-200 bg-white px-3 text-sm text-slate-700 outline-none transition focus:border-[#10B981]/50 focus:ring-2 focus:ring-[#10B981]/20"
|
||||
>
|
||||
{PAGE_SIZE_OPTIONS.map((size) => (
|
||||
<option key={size} value={size}>
|
||||
@@ -412,7 +412,7 @@ function Pagination({
|
||||
type="button"
|
||||
onClick={() => onPageChange(page - 1)}
|
||||
disabled={page <= 1}
|
||||
className="inline-flex h-9 items-center gap-1 rounded-xl border border-slate-200 px-3 text-sm font-medium text-slate-700 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D] disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent disabled:hover:text-slate-700"
|
||||
className="inline-flex h-9 items-center gap-1 rounded-xl border border-slate-200 px-3 text-sm font-medium text-slate-700 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981] disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent disabled:hover:text-slate-700"
|
||||
>
|
||||
<ChevronLeft className="h-4 w-4" />
|
||||
Prev
|
||||
@@ -428,8 +428,8 @@ function Pagination({
|
||||
aria-current={isActive ? "page" : undefined}
|
||||
className={
|
||||
isActive
|
||||
? "h-9 w-9 rounded-xl bg-[#33578D] text-sm font-medium text-white"
|
||||
: "h-9 w-9 rounded-xl border border-slate-200 text-sm font-medium text-slate-700 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D]"
|
||||
? "h-9 w-9 rounded-xl bg-[#10B981] text-sm font-medium text-white"
|
||||
: "h-9 w-9 rounded-xl border border-slate-200 text-sm font-medium text-slate-700 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981]"
|
||||
}
|
||||
>
|
||||
{p}
|
||||
@@ -441,7 +441,7 @@ function Pagination({
|
||||
type="button"
|
||||
onClick={() => onPageChange(page + 1)}
|
||||
disabled={page >= totalPages}
|
||||
className="inline-flex h-9 items-center gap-1 rounded-xl border border-slate-200 px-3 text-sm font-medium text-slate-700 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D] disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent disabled:hover:text-slate-700"
|
||||
className="inline-flex h-9 items-center gap-1 rounded-xl border border-slate-200 px-3 text-sm font-medium text-slate-700 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981] disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent disabled:hover:text-slate-700"
|
||||
>
|
||||
Next
|
||||
<ChevronRight className="h-4 w-4" />
|
||||
@@ -465,10 +465,10 @@ function StatCard({
|
||||
const iconWrap =
|
||||
tone === "danger"
|
||||
? "bg-red-100 text-red-600"
|
||||
: "bg-[#33578D]/10 text-[#33578D]";
|
||||
: "bg-[#10B981] text-white";
|
||||
|
||||
return (
|
||||
<div className="rounded-3xl bg-white p-6 shadow-sm transition hover:shadow-md hover:ring-1 hover:ring-[#33578D]/20">
|
||||
<div className="rounded-3xl bg-white p-6 shadow-sm transition hover:shadow-md hover:ring-1 hover:ring-[#10B981]/20">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm text-slate-500">{title}</p>
|
||||
|
||||
@@ -42,7 +42,7 @@ export interface NewConsignmentPageProps {
|
||||
}
|
||||
|
||||
const selectClass =
|
||||
"flex h-10 w-full rounded-md border border-slate-200 bg-white px-3 py-2 text-sm text-slate-700 shadow-xs outline-none transition hover:border-slate-300 focus:border-[#33578D]/50 focus:ring-2 focus:ring-[#33578D]/20";
|
||||
"flex h-10 w-full rounded-md border border-slate-200 bg-white px-3 py-2 text-sm text-slate-700 shadow-xs outline-none transition hover:border-slate-300 focus:border-[#10B981]/50 focus:ring-2 focus:ring-[#10B981]/20";
|
||||
|
||||
export default function NewConsignmentPage({
|
||||
mode = "create",
|
||||
@@ -198,7 +198,7 @@ export default function NewConsignmentPage({
|
||||
<input
|
||||
type="checkbox"
|
||||
defaultChecked={consignment?.hazardous ?? false}
|
||||
className="h-4 w-4 rounded border-slate-300 text-[#33578D] focus:ring-[#33578D]/20"
|
||||
className="h-4 w-4 rounded border-slate-300 text-[#10B981] focus:ring-[#10B981]/20"
|
||||
/>
|
||||
<span>Mark as hazardous (DG)</span>
|
||||
</label>
|
||||
@@ -225,7 +225,7 @@ export default function NewConsignmentPage({
|
||||
|
||||
<div className="flex justify-end gap-3">
|
||||
<Button variant="outline">Cancel</Button>
|
||||
<Button className="bg-[#33578D] text-white hover:bg-[#33578D]/90">
|
||||
<Button className="bg-[#10B981] text-white hover:bg-[#10B981]/90">
|
||||
{submitLabel}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -42,7 +42,7 @@ export default function CustomerDetailPage() {
|
||||
</p>
|
||||
<Link
|
||||
to="/customers"
|
||||
className="mt-6 inline-flex items-center gap-2 rounded-2xl bg-[#33578D] px-4 py-2 text-sm font-medium text-white transition hover:bg-[#33578D]/90"
|
||||
className="mt-6 inline-flex items-center gap-2 rounded-2xl bg-[#10B981] px-4 py-2 text-sm font-medium text-white transition hover:bg-[#10B981]/90"
|
||||
>
|
||||
<ArrowLeft className="h-4 w-4" />
|
||||
Back to Customers
|
||||
@@ -67,7 +67,7 @@ export default function CustomerDetailPage() {
|
||||
<div className="rounded-3xl bg-white p-6 shadow-sm">
|
||||
<div className="flex flex-col gap-4 md:flex-row md:items-center md:justify-between">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="flex h-16 w-16 items-center justify-center rounded-2xl bg-[#33578D]/10 text-[#33578D]">
|
||||
<div className="flex h-16 w-16 items-center justify-center rounded-2xl bg-[#10B981] text-white">
|
||||
<User className="h-8 w-8" />
|
||||
</div>
|
||||
|
||||
@@ -103,7 +103,7 @@ export default function CustomerDetailPage() {
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex items-center gap-2 rounded-2xl bg-[#33578D] px-4 py-2 text-sm font-medium text-white transition hover:bg-[#33578D]/90"
|
||||
className="inline-flex items-center gap-2 rounded-2xl bg-[#10B981] px-4 py-2 text-sm font-medium text-white transition hover:bg-[#10B981]/90"
|
||||
>
|
||||
Edit Customer
|
||||
</button>
|
||||
@@ -183,7 +183,7 @@ export default function CustomerDetailPage() {
|
||||
|
||||
<DetailCard title="Notes">
|
||||
<div className="flex items-start gap-3 text-sm text-slate-700">
|
||||
<StickyNote className="mt-0.5 h-4 w-4 text-[#33578D]" />
|
||||
<StickyNote className="mt-0.5 h-4 w-4 text-[#10B981]" />
|
||||
<p className="leading-relaxed">{customer.notes}</p>
|
||||
</div>
|
||||
</DetailCard>
|
||||
@@ -219,7 +219,7 @@ function DetailRow({
|
||||
}) {
|
||||
return (
|
||||
<div className="flex items-start gap-3">
|
||||
<div className="mt-0.5 text-[#33578D]">{icon}</div>
|
||||
<div className="mt-0.5 text-[#10B981]">{icon}</div>
|
||||
<div className="flex-1">
|
||||
<p className="text-xs font-medium text-slate-500">{label}</p>
|
||||
<p className="mt-0.5 text-sm text-slate-900">{value}</p>
|
||||
|
||||
@@ -58,14 +58,14 @@ export default function CustomerPage() {
|
||||
<input
|
||||
type="search"
|
||||
placeholder="Search customers..."
|
||||
className="h-10 w-full rounded-2xl border border-slate-200 bg-white pl-10 pr-4 text-sm text-slate-700 outline-none transition placeholder:text-slate-400 focus:border-[#33578D]/50 focus:ring-2 focus:ring-[#33578D]/20"
|
||||
className="h-10 w-full rounded-2xl border border-slate-200 bg-white pl-10 pr-4 text-sm text-slate-700 outline-none transition placeholder:text-slate-400 focus:border-[#10B981]/50 focus:ring-2 focus:ring-[#10B981]/20"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<NewCustomerPage>
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex items-center justify-center gap-2 rounded-2xl bg-[#33578D] px-4 py-2 text-sm font-medium text-white transition hover:bg-[#33578D]/90"
|
||||
className="inline-flex items-center justify-center gap-2 rounded-2xl bg-[#10B981] px-4 py-2 text-sm font-medium text-white transition hover:bg-[#10B981]/90"
|
||||
>
|
||||
<Plus className="h-4 w-4" />
|
||||
Add Customer
|
||||
@@ -107,7 +107,7 @@ export default function CustomerPage() {
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<button className="inline-flex items-center gap-2 rounded-2xl border border-slate-200 px-4 py-2 text-sm font-medium text-slate-700 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D]">
|
||||
<button className="inline-flex items-center gap-2 rounded-2xl border border-slate-200 px-4 py-2 text-sm font-medium text-slate-700 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981]">
|
||||
<Filter className="h-4 w-4" />
|
||||
Filter
|
||||
</button>
|
||||
@@ -129,11 +129,11 @@ export default function CustomerPage() {
|
||||
{paginated.map((customer) => (
|
||||
<tr
|
||||
key={customer.id}
|
||||
className="border-t border-slate-100 transition hover:bg-[#33578D]/5"
|
||||
className="border-t border-slate-100 transition hover:bg-[#10B981]/5"
|
||||
>
|
||||
<td className="px-6 py-4">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-[#33578D]/10 text-[#33578D]">
|
||||
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-[#10B981] text-white">
|
||||
<User className="h-5 w-5" />
|
||||
</div>
|
||||
|
||||
@@ -164,7 +164,7 @@ export default function CustomerPage() {
|
||||
<div className="flex justify-end gap-2">
|
||||
<Link
|
||||
to={`/customers/${customer.id}`}
|
||||
className="rounded-xl border border-slate-200 p-2 text-slate-600 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D]"
|
||||
className="rounded-xl border border-slate-200 p-2 text-slate-600 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981]"
|
||||
>
|
||||
<Eye className="h-4 w-4" />
|
||||
</Link>
|
||||
@@ -186,7 +186,7 @@ export default function CustomerPage() {
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
className="rounded-xl border border-slate-200 p-2 text-slate-600 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D]"
|
||||
className="rounded-xl border border-slate-200 p-2 text-slate-600 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981]"
|
||||
>
|
||||
<Pencil className="h-4 w-4" />
|
||||
</button>
|
||||
@@ -258,7 +258,7 @@ function Pagination({
|
||||
id="page-size"
|
||||
value={pageSize}
|
||||
onChange={(e) => onPageSizeChange(Number(e.target.value))}
|
||||
className="h-9 rounded-xl border border-slate-200 bg-white px-3 text-sm text-slate-700 outline-none transition focus:border-[#33578D]/50 focus:ring-2 focus:ring-[#33578D]/20"
|
||||
className="h-9 rounded-xl border border-slate-200 bg-white px-3 text-sm text-slate-700 outline-none transition focus:border-[#10B981]/50 focus:ring-2 focus:ring-[#10B981]/20"
|
||||
>
|
||||
{PAGE_SIZE_OPTIONS.map((size) => (
|
||||
<option key={size} value={size}>
|
||||
@@ -276,7 +276,7 @@ function Pagination({
|
||||
type="button"
|
||||
onClick={() => onPageChange(page - 1)}
|
||||
disabled={page <= 1}
|
||||
className="inline-flex h-9 items-center gap-1 rounded-xl border border-slate-200 px-3 text-sm font-medium text-slate-700 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D] disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent disabled:hover:text-slate-700"
|
||||
className="inline-flex h-9 items-center gap-1 rounded-xl border border-slate-200 px-3 text-sm font-medium text-slate-700 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981] disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent disabled:hover:text-slate-700"
|
||||
>
|
||||
<ChevronLeft className="h-4 w-4" />
|
||||
Prev
|
||||
@@ -292,8 +292,8 @@ function Pagination({
|
||||
aria-current={isActive ? "page" : undefined}
|
||||
className={
|
||||
isActive
|
||||
? "h-9 w-9 rounded-xl bg-[#33578D] text-sm font-medium text-white"
|
||||
: "h-9 w-9 rounded-xl border border-slate-200 text-sm font-medium text-slate-700 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D]"
|
||||
? "h-9 w-9 rounded-xl bg-[#10B981] text-sm font-medium text-white"
|
||||
: "h-9 w-9 rounded-xl border border-slate-200 text-sm font-medium text-slate-700 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981]"
|
||||
}
|
||||
>
|
||||
{p}
|
||||
@@ -305,7 +305,7 @@ function Pagination({
|
||||
type="button"
|
||||
onClick={() => onPageChange(page + 1)}
|
||||
disabled={page >= totalPages}
|
||||
className="inline-flex h-9 items-center gap-1 rounded-xl border border-slate-200 px-3 text-sm font-medium text-slate-700 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D] disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent disabled:hover:text-slate-700"
|
||||
className="inline-flex h-9 items-center gap-1 rounded-xl border border-slate-200 px-3 text-sm font-medium text-slate-700 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981] disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent disabled:hover:text-slate-700"
|
||||
>
|
||||
Next
|
||||
<ChevronRight className="h-4 w-4" />
|
||||
@@ -325,14 +325,14 @@ function StatCard({
|
||||
icon: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<div className="rounded-3xl bg-white p-6 shadow-sm transition hover:shadow-md hover:ring-1 hover:ring-[#33578D]/20">
|
||||
<div className="rounded-3xl bg-white p-6 shadow-sm transition hover:shadow-md hover:ring-1 hover:ring-[#10B981]/20">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm text-slate-500">{title}</p>
|
||||
<h3 className="mt-2 text-3xl font-bold text-slate-900">{value}</h3>
|
||||
</div>
|
||||
|
||||
<div className="flex h-12 w-12 items-center justify-center rounded-2xl bg-[#33578D]/10 text-[#33578D]">
|
||||
<div className="flex h-12 w-12 items-center justify-center rounded-2xl bg-[#10B981] text-white">
|
||||
{icon}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -90,7 +90,7 @@ export default function NewCustomerPage({
|
||||
|
||||
<select
|
||||
defaultValue={customer?.customerType ?? "Importer"}
|
||||
className="flex h-10 w-full rounded-md border border-slate-200 bg-white px-3 py-2 text-sm text-slate-700 shadow-xs outline-none transition hover:border-slate-300 focus:border-[#33578D]/50 focus:ring-2 focus:ring-[#33578D]/20"
|
||||
className="flex h-10 w-full rounded-md border border-slate-200 bg-white px-3 py-2 text-sm text-slate-700 shadow-xs outline-none transition hover:border-slate-300 focus:border-[#10B981]/50 focus:ring-2 focus:ring-[#10B981]/20"
|
||||
>
|
||||
<option>Importer</option>
|
||||
<option>Exporter</option>
|
||||
@@ -213,7 +213,7 @@ export default function NewCustomerPage({
|
||||
<div className="flex justify-end gap-3">
|
||||
<Button variant="outline">Cancel</Button>
|
||||
|
||||
<Button className="bg-[#33578D] text-white hover:bg-[#33578D]/90">
|
||||
<Button className="bg-[#10B981] text-white hover:bg-[#10B981]/90">
|
||||
{submitLabel}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -37,9 +37,11 @@ import { invoices } from "../billing/invoices.mock";
|
||||
import { shipments } from "../tracking/shipments.mock";
|
||||
import { trains } from "../trains/trains.mock";
|
||||
|
||||
const BRAND = "#33578D";
|
||||
const BRAND_LIGHT = "#6B8AB8";
|
||||
const BRAND_LIGHTER = "#B7C7DE";
|
||||
// Main brand color: #10B981 (emerald-500). Lighter variants for chart
|
||||
// hierarchy so multi-series lines/areas/bars stay visually distinct.
|
||||
const BRAND = "#10B981"; // emerald-500
|
||||
const BRAND_LIGHT = "#6EE7B7"; // emerald-300
|
||||
const BRAND_LIGHTER = "#D1FAE5"; // emerald-100
|
||||
|
||||
const STATUS_PALETTE: Record<string, string> = {
|
||||
Pending: "#d97706",
|
||||
@@ -179,10 +181,10 @@ export default function DashboardPage() {
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex flex-wrap items-center gap-2 text-xs">
|
||||
<span className="rounded-full cursor-pointer hover:scale-110 text-white bg-gradient-to-r from-[#33578D] to-[#4a72ad] px-3 py-1 backdrop-blur">
|
||||
<span className="rounded-full cursor-pointer hover:scale-110 text-white bg-gradient-to-r from-[#059669] to-[#10B981] px-3 py-1 backdrop-blur">
|
||||
● Live
|
||||
</span>
|
||||
<span className="rounded-full cursor-pointer hover:scale-110 text-white bg-gradient-to-r from-[#33578D] to-[#4a72ad] px-3 py-1 backdrop-blur">
|
||||
<span className="rounded-full cursor-pointer hover:scale-110 text-white bg-gradient-to-r from-[#059669] to-[#10B981] px-3 py-1 backdrop-blur">
|
||||
Last 30 days
|
||||
</span>
|
||||
</div>
|
||||
@@ -417,7 +419,7 @@ export default function DashboardPage() {
|
||||
width={100}
|
||||
/>
|
||||
<Tooltip
|
||||
cursor={{ fill: "#33578D14" }}
|
||||
cursor={{ fill: "#10B98114" }}
|
||||
contentStyle={{
|
||||
backgroundColor: "white",
|
||||
border: "1px solid #e2e8f0",
|
||||
@@ -454,7 +456,7 @@ export default function DashboardPage() {
|
||||
/>
|
||||
<YAxis stroke="#94a3b8" style={{ fontSize: "12px" }} />
|
||||
<Tooltip
|
||||
cursor={{ fill: "#33578D14" }}
|
||||
cursor={{ fill: "#10B98114" }}
|
||||
contentStyle={{
|
||||
backgroundColor: "white",
|
||||
border: "1px solid #e2e8f0",
|
||||
@@ -517,7 +519,7 @@ export default function DashboardPage() {
|
||||
</div>
|
||||
<Link
|
||||
to="/tracking"
|
||||
className="inline-flex items-center gap-1 text-xs font-medium text-[#33578D] transition hover:underline"
|
||||
className="inline-flex items-center gap-1 text-xs font-medium text-[#10B981] transition hover:underline"
|
||||
>
|
||||
View all
|
||||
<ArrowRight className="h-3 w-3" />
|
||||
@@ -528,7 +530,7 @@ export default function DashboardPage() {
|
||||
{recentShipments.map((s) => (
|
||||
<li
|
||||
key={s.id}
|
||||
className="flex items-center justify-between gap-3 rounded-2xl border border-slate-100 p-3 transition hover:border-[#33578D]/20 hover:bg-[#33578D]/5"
|
||||
className="flex items-center justify-between gap-3 rounded-2xl border border-slate-100 p-3 transition hover:border-[#10B981]/20 hover:bg-[#10B981]/5"
|
||||
>
|
||||
<div className="flex items-center gap-3 overflow-hidden">
|
||||
<CircleDot
|
||||
@@ -613,7 +615,7 @@ function KpiCard({
|
||||
const TrendIcon = trend === "up" ? ArrowUpRight : ArrowDownRight;
|
||||
|
||||
return (
|
||||
<div className="rounded-3xl bg-white p-6 shadow-sm transition hover:shadow-md hover:ring-1 hover:ring-[#33578D]/20">
|
||||
<div className="rounded-3xl bg-white p-6 shadow-sm transition hover:shadow-md hover:ring-1 hover:ring-[#10B981]/20">
|
||||
<div className="flex items-start justify-between">
|
||||
<div>
|
||||
<p className="text-sm text-slate-500">{label}</p>
|
||||
@@ -626,7 +628,7 @@ function KpiCard({
|
||||
<span className="text-slate-400">vs last period</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex h-10 w-10 items-center justify-center rounded-2xl bg-[#33578D]/10 text-[#33578D]">
|
||||
<div className="flex h-10 w-10 items-center justify-center rounded-2xl bg-[#10B981] text-white">
|
||||
{icon}
|
||||
</div>
|
||||
</div>
|
||||
@@ -674,10 +676,10 @@ function SummaryCard({
|
||||
return (
|
||||
<Link
|
||||
to={href}
|
||||
className="flex items-center justify-between rounded-3xl bg-white p-4 shadow-sm transition hover:shadow-md hover:ring-1 hover:ring-[#33578D]/20"
|
||||
className="flex items-center justify-between rounded-3xl bg-white p-4 shadow-sm transition hover:shadow-md hover:ring-1 hover:ring-[#10B981]/20"
|
||||
>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex h-9 w-9 items-center justify-center rounded-xl bg-[#33578D]/10 text-[#33578D]">
|
||||
<div className="flex h-9 w-9 items-center justify-center rounded-xl bg-[#10B981] text-white">
|
||||
{icon}
|
||||
</div>
|
||||
<div>
|
||||
|
||||
@@ -110,14 +110,14 @@ export default function DocumentsPage() {
|
||||
setPage(1);
|
||||
}}
|
||||
placeholder="Search documents..."
|
||||
className="h-10 w-full rounded-2xl border border-slate-200 bg-white pl-10 pr-4 text-sm text-slate-700 outline-none transition placeholder:text-slate-400 focus:border-[#33578D]/50 focus:ring-2 focus:ring-[#33578D]/20"
|
||||
className="h-10 w-full rounded-2xl border border-slate-200 bg-white pl-10 pr-4 text-sm text-slate-700 outline-none transition placeholder:text-slate-400 focus:border-[#10B981]/50 focus:ring-2 focus:ring-[#10B981]/20"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<NewDocumentPage>
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex items-center justify-center gap-2 rounded-2xl bg-[#33578D] px-4 py-2 text-sm font-medium text-white transition hover:bg-[#33578D]/90"
|
||||
className="inline-flex items-center justify-center gap-2 rounded-2xl bg-[#10B981] px-4 py-2 text-sm font-medium text-white transition hover:bg-[#10B981]/90"
|
||||
>
|
||||
<Plus className="h-4 w-4" />
|
||||
Upload Document
|
||||
@@ -169,8 +169,8 @@ export default function DocumentsPage() {
|
||||
}}
|
||||
className={
|
||||
isActive
|
||||
? "inline-flex items-center gap-2 rounded-2xl bg-[#33578D] px-4 py-2 text-sm font-medium text-white"
|
||||
: "inline-flex items-center gap-2 rounded-2xl px-4 py-2 text-sm font-medium text-slate-600 transition hover:bg-[#33578D]/10 hover:text-[#33578D]"
|
||||
? "inline-flex items-center gap-2 rounded-2xl bg-[#10B981] px-4 py-2 text-sm font-medium text-white"
|
||||
: "inline-flex items-center gap-2 rounded-2xl px-4 py-2 text-sm font-medium text-slate-600 transition hover:bg-[#10B981]/10 hover:text-[#10B981]"
|
||||
}
|
||||
>
|
||||
{f}
|
||||
@@ -266,8 +266,8 @@ function ViewToggleButton({
|
||||
aria-pressed={active}
|
||||
className={
|
||||
active
|
||||
? "inline-flex items-center gap-2 rounded-lg bg-white px-3 py-1.5 text-sm font-medium text-[#33578D] shadow-sm"
|
||||
: "inline-flex items-center gap-2 rounded-lg px-3 py-1.5 text-sm font-medium text-slate-600 transition hover:text-[#33578D]"
|
||||
? "inline-flex items-center gap-2 rounded-lg bg-white px-3 py-1.5 text-sm font-medium text-[#10B981] shadow-sm"
|
||||
: "inline-flex items-center gap-2 rounded-lg px-3 py-1.5 text-sm font-medium text-slate-600 transition hover:text-[#10B981]"
|
||||
}
|
||||
>
|
||||
{children}
|
||||
@@ -276,7 +276,7 @@ function ViewToggleButton({
|
||||
}
|
||||
|
||||
function FormatIcon({ format }: { format: DocumentFormat }) {
|
||||
const className = "h-5 w-5 text-[#33578D]";
|
||||
const className = "h-5 w-5 text-[#10B981]";
|
||||
if (format === "PDF") return <FileText className={className} />;
|
||||
if (format === "DOCX") return <FileText className={className} />;
|
||||
if (format === "XLSX") return <FileSpreadsheet className={className} />;
|
||||
@@ -287,10 +287,10 @@ function FormatIcon({ format }: { format: DocumentFormat }) {
|
||||
|
||||
function DocumentCard({ doc }: { doc: DocumentRecord }) {
|
||||
return (
|
||||
<div className="flex flex-col gap-4 rounded-3xl bg-white p-5 shadow-sm transition hover:shadow-md hover:ring-1 hover:ring-[#33578D]/20">
|
||||
<div className="flex flex-col gap-4 rounded-3xl bg-white p-5 shadow-sm transition hover:shadow-md hover:ring-1 hover:ring-[#10B981]/20">
|
||||
<div className="flex items-start justify-between gap-3">
|
||||
<div className="flex items-start gap-3">
|
||||
<div className="flex h-12 w-12 items-center justify-center rounded-2xl bg-[#33578D]/10">
|
||||
<div className="flex h-12 w-12 items-center justify-center rounded-2xl bg-[#10B981]/10">
|
||||
<FormatIcon format={doc.format} />
|
||||
</div>
|
||||
<div className="min-w-0 flex-1">
|
||||
@@ -316,14 +316,14 @@ function DocumentCard({ doc }: { doc: DocumentRecord }) {
|
||||
<button
|
||||
type="button"
|
||||
aria-label="Preview"
|
||||
className="rounded-xl border border-slate-200 p-2 text-slate-600 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D]"
|
||||
className="rounded-xl border border-slate-200 p-2 text-slate-600 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981]"
|
||||
>
|
||||
<Eye className="h-4 w-4" />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
aria-label="Download"
|
||||
className="rounded-xl border border-slate-200 p-2 text-slate-600 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D]"
|
||||
className="rounded-xl border border-slate-200 p-2 text-slate-600 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981]"
|
||||
>
|
||||
<Download className="h-4 w-4" />
|
||||
</button>
|
||||
@@ -340,7 +340,7 @@ function DocumentCard({ doc }: { doc: DocumentRecord }) {
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
className="rounded-xl border border-slate-200 p-2 text-slate-600 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D]"
|
||||
className="rounded-xl border border-slate-200 p-2 text-slate-600 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981]"
|
||||
>
|
||||
<Pencil className="h-4 w-4" />
|
||||
</button>
|
||||
@@ -380,7 +380,7 @@ function DocumentTable({ documents: rows }: { documents: DocumentRecord[] }) {
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<button className="inline-flex items-center gap-2 rounded-2xl border border-slate-200 px-4 py-2 text-sm font-medium text-slate-700 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D]">
|
||||
<button className="inline-flex items-center gap-2 rounded-2xl border border-slate-200 px-4 py-2 text-sm font-medium text-slate-700 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981]">
|
||||
<Filter className="h-4 w-4" />
|
||||
Filter
|
||||
</button>
|
||||
@@ -404,11 +404,11 @@ function DocumentTable({ documents: rows }: { documents: DocumentRecord[] }) {
|
||||
{rows.map((doc) => (
|
||||
<tr
|
||||
key={doc.id}
|
||||
className="border-t border-slate-100 transition hover:bg-[#33578D]/5"
|
||||
className="border-t border-slate-100 transition hover:bg-[#10B981]/5"
|
||||
>
|
||||
<td className="px-6 py-4">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-[#33578D]/10">
|
||||
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-[#10B981]/10">
|
||||
<FormatIcon format={doc.format} />
|
||||
</div>
|
||||
<div className="min-w-0">
|
||||
@@ -448,14 +448,14 @@ function DocumentTable({ documents: rows }: { documents: DocumentRecord[] }) {
|
||||
<button
|
||||
type="button"
|
||||
aria-label="Preview"
|
||||
className="rounded-xl border border-slate-200 p-2 text-slate-600 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D]"
|
||||
className="rounded-xl border border-slate-200 p-2 text-slate-600 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981]"
|
||||
>
|
||||
<Eye className="h-4 w-4" />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
aria-label="Download"
|
||||
className="rounded-xl border border-slate-200 p-2 text-slate-600 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D]"
|
||||
className="rounded-xl border border-slate-200 p-2 text-slate-600 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981]"
|
||||
>
|
||||
<Download className="h-4 w-4" />
|
||||
</button>
|
||||
@@ -472,7 +472,7 @@ function DocumentTable({ documents: rows }: { documents: DocumentRecord[] }) {
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
className="rounded-xl border border-slate-200 p-2 text-slate-600 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D]"
|
||||
className="rounded-xl border border-slate-200 p-2 text-slate-600 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981]"
|
||||
>
|
||||
<Pencil className="h-4 w-4" />
|
||||
</button>
|
||||
@@ -530,7 +530,7 @@ function Pagination({
|
||||
id="document-page-size"
|
||||
value={pageSize}
|
||||
onChange={(e) => onPageSizeChange(Number(e.target.value))}
|
||||
className="h-9 rounded-xl border border-slate-200 bg-white px-3 text-sm text-slate-700 outline-none transition focus:border-[#33578D]/50 focus:ring-2 focus:ring-[#33578D]/20"
|
||||
className="h-9 rounded-xl border border-slate-200 bg-white px-3 text-sm text-slate-700 outline-none transition focus:border-[#10B981]/50 focus:ring-2 focus:ring-[#10B981]/20"
|
||||
>
|
||||
{PAGE_SIZE_OPTIONS.map((size) => (
|
||||
<option key={size} value={size}>
|
||||
@@ -548,7 +548,7 @@ function Pagination({
|
||||
type="button"
|
||||
onClick={() => onPageChange(page - 1)}
|
||||
disabled={page <= 1}
|
||||
className="inline-flex h-9 items-center gap-1 rounded-xl border border-slate-200 px-3 text-sm font-medium text-slate-700 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D] disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent disabled:hover:text-slate-700"
|
||||
className="inline-flex h-9 items-center gap-1 rounded-xl border border-slate-200 px-3 text-sm font-medium text-slate-700 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981] disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent disabled:hover:text-slate-700"
|
||||
>
|
||||
<ChevronLeft className="h-4 w-4" />
|
||||
Prev
|
||||
@@ -564,8 +564,8 @@ function Pagination({
|
||||
aria-current={isActive ? "page" : undefined}
|
||||
className={
|
||||
isActive
|
||||
? "h-9 w-9 rounded-xl bg-[#33578D] text-sm font-medium text-white"
|
||||
: "h-9 w-9 rounded-xl border border-slate-200 text-sm font-medium text-slate-700 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D]"
|
||||
? "h-9 w-9 rounded-xl bg-[#10B981] text-sm font-medium text-white"
|
||||
: "h-9 w-9 rounded-xl border border-slate-200 text-sm font-medium text-slate-700 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981]"
|
||||
}
|
||||
>
|
||||
{p}
|
||||
@@ -577,7 +577,7 @@ function Pagination({
|
||||
type="button"
|
||||
onClick={() => onPageChange(page + 1)}
|
||||
disabled={page >= totalPages}
|
||||
className="inline-flex h-9 items-center gap-1 rounded-xl border border-slate-200 px-3 text-sm font-medium text-slate-700 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D] disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent disabled:hover:text-slate-700"
|
||||
className="inline-flex h-9 items-center gap-1 rounded-xl border border-slate-200 px-3 text-sm font-medium text-slate-700 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981] disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent disabled:hover:text-slate-700"
|
||||
>
|
||||
Next
|
||||
<ChevronRight className="h-4 w-4" />
|
||||
@@ -597,13 +597,13 @@ function StatCard({
|
||||
icon: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<div className="rounded-3xl bg-white p-6 shadow-sm transition hover:shadow-md hover:ring-1 hover:ring-[#33578D]/20">
|
||||
<div className="rounded-3xl bg-white p-6 shadow-sm transition hover:shadow-md hover:ring-1 hover:ring-[#10B981]/20">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm text-slate-500">{title}</p>
|
||||
<h3 className="mt-2 text-2xl font-bold text-slate-900">{value}</h3>
|
||||
</div>
|
||||
<div className="flex h-12 w-12 items-center justify-center rounded-2xl bg-[#33578D]/10 text-[#33578D]">
|
||||
<div className="flex h-12 w-12 items-center justify-center rounded-2xl bg-[#10B981] text-white">
|
||||
{icon}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -39,7 +39,7 @@ export interface NewDocumentPageProps {
|
||||
}
|
||||
|
||||
const selectClass =
|
||||
"flex h-10 w-full rounded-md border border-slate-200 bg-white px-3 py-2 text-sm text-slate-700 shadow-xs outline-none transition hover:border-slate-300 focus:border-[#33578D]/50 focus:ring-2 focus:ring-[#33578D]/20";
|
||||
"flex h-10 w-full rounded-md border border-slate-200 bg-white px-3 py-2 text-sm text-slate-700 shadow-xs outline-none transition hover:border-slate-300 focus:border-[#10B981]/50 focus:ring-2 focus:ring-[#10B981]/20";
|
||||
|
||||
export default function NewDocumentPage({
|
||||
mode = "create",
|
||||
@@ -99,9 +99,9 @@ export default function NewDocumentPage({
|
||||
<Label>File</Label>
|
||||
<label
|
||||
htmlFor="document-file-input"
|
||||
className="mt-1 flex cursor-pointer flex-col items-center justify-center gap-2 rounded-2xl border-2 border-dashed border-slate-200 bg-[#33578D]/5 p-8 text-center transition hover:border-[#33578D]/40 hover:bg-[#33578D]/10"
|
||||
className="mt-1 flex cursor-pointer flex-col items-center justify-center gap-2 rounded-2xl border-2 border-dashed border-slate-200 bg-[#10B981]/5 p-8 text-center transition hover:border-[#10B981]/40 hover:bg-[#10B981]/10"
|
||||
>
|
||||
<div className="flex h-12 w-12 items-center justify-center rounded-2xl bg-[#33578D]/10 text-[#33578D]">
|
||||
<div className="flex h-12 w-12 items-center justify-center rounded-2xl bg-[#10B981] text-white">
|
||||
<FileUp className="h-6 w-6" />
|
||||
</div>
|
||||
<p className="text-sm font-medium text-slate-900">
|
||||
@@ -232,7 +232,7 @@ export default function NewDocumentPage({
|
||||
|
||||
<div className="flex justify-end gap-3">
|
||||
<Button variant="outline">Cancel</Button>
|
||||
<Button className="bg-[#33578D] text-white hover:bg-[#33578D]/90">
|
||||
<Button className="bg-[#10B981] text-white hover:bg-[#10B981]/90">
|
||||
{submitLabel}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -58,7 +58,7 @@ export default function MyPortalPage() {
|
||||
<Breadcrumbs items={[{ label: "My Portal" }]} />
|
||||
|
||||
{/* Welcome banner */}
|
||||
<div className="overflow-hidden rounded-3xl bg-gradient-to-r from-[#33578D] to-[#4a72ad] p-6 text-white shadow-sm">
|
||||
<div className="overflow-hidden rounded-3xl bg-gradient-to-r from-[#059669] to-[#10B981] p-6 text-white shadow-sm">
|
||||
<div className="flex flex-col gap-4 md:flex-row md:items-center md:justify-between">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="flex h-16 w-16 items-center justify-center rounded-2xl bg-white/15 text-2xl font-bold backdrop-blur">
|
||||
@@ -84,7 +84,7 @@ export default function MyPortalPage() {
|
||||
<NewBookingPage>
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex items-center gap-2 rounded-2xl bg-white px-4 py-2 text-sm font-semibold text-[#33578D] transition hover:bg-slate-100"
|
||||
className="inline-flex items-center gap-2 rounded-2xl bg-white px-4 py-2 text-sm font-semibold text-[#10B981] transition hover:bg-slate-100"
|
||||
>
|
||||
<Plus className="h-4 w-4" />
|
||||
New Booking
|
||||
@@ -146,7 +146,7 @@ export default function MyPortalPage() {
|
||||
</div>
|
||||
<Link
|
||||
to="/tracking"
|
||||
className="inline-flex items-center gap-1 text-sm font-medium text-[#33578D] transition hover:underline"
|
||||
className="inline-flex items-center gap-1 text-sm font-medium text-[#10B981] transition hover:underline"
|
||||
>
|
||||
View all
|
||||
<ArrowRight className="h-4 w-4" />
|
||||
@@ -162,7 +162,7 @@ export default function MyPortalPage() {
|
||||
{activeShipments.slice(0, 4).map((shipment) => (
|
||||
<div
|
||||
key={shipment.id}
|
||||
className="rounded-2xl border border-slate-100 p-4 transition hover:border-[#33578D]/20 hover:bg-[#33578D]/5"
|
||||
className="rounded-2xl border border-slate-100 p-4 transition hover:border-[#10B981]/20 hover:bg-[#10B981]/5"
|
||||
>
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="font-semibold text-slate-900">
|
||||
@@ -177,14 +177,14 @@ export default function MyPortalPage() {
|
||||
</p>
|
||||
<div className="mt-3 flex items-center justify-between text-xs text-slate-500">
|
||||
<span className="flex items-center gap-1">
|
||||
<MapPin className="h-3 w-3 text-[#33578D]" />
|
||||
<MapPin className="h-3 w-3 text-[#10B981]" />
|
||||
{shipment.currentLocation}
|
||||
</span>
|
||||
<span>ETA {shipment.eta}</span>
|
||||
</div>
|
||||
<div className="mt-2 h-1.5 w-full overflow-hidden rounded-full bg-slate-100">
|
||||
<div
|
||||
className="h-full rounded-full bg-[#33578D] transition-all"
|
||||
className="h-full rounded-full bg-[#10B981] transition-all"
|
||||
style={{ width: `${shipment.progress}%` }}
|
||||
/>
|
||||
</div>
|
||||
@@ -209,7 +209,7 @@ export default function MyPortalPage() {
|
||||
</div>
|
||||
<Link
|
||||
to="/bookings"
|
||||
className="inline-flex items-center gap-1 text-sm font-medium text-[#33578D] transition hover:underline"
|
||||
className="inline-flex items-center gap-1 text-sm font-medium text-[#10B981] transition hover:underline"
|
||||
>
|
||||
View all
|
||||
<ArrowRight className="h-4 w-4" />
|
||||
@@ -236,7 +236,7 @@ export default function MyPortalPage() {
|
||||
{recentBookings.map((booking) => (
|
||||
<tr
|
||||
key={booking.id}
|
||||
className="border-t border-slate-100 transition hover:bg-[#33578D]/5"
|
||||
className="border-t border-slate-100 transition hover:bg-[#10B981]/5"
|
||||
>
|
||||
<td className="py-3 font-medium text-slate-900">
|
||||
{booking.reference}
|
||||
@@ -254,7 +254,7 @@ export default function MyPortalPage() {
|
||||
<Link
|
||||
to={`/bookings/${booking.id}`}
|
||||
aria-label="View booking"
|
||||
className="inline-flex h-7 w-7 items-center justify-center rounded-lg text-slate-500 transition hover:bg-[#33578D]/10 hover:text-[#33578D]"
|
||||
className="inline-flex h-7 w-7 items-center justify-center rounded-lg text-slate-500 transition hover:bg-[#10B981]/10 hover:text-[#10B981]"
|
||||
>
|
||||
<Eye className="h-4 w-4" />
|
||||
</Link>
|
||||
@@ -299,7 +299,7 @@ export default function MyPortalPage() {
|
||||
|
||||
<Link
|
||||
to={`/customers/${me.id}`}
|
||||
className="mt-4 inline-flex w-full items-center justify-center gap-2 rounded-2xl border border-slate-200 px-4 py-2 text-sm font-medium text-slate-700 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D]"
|
||||
className="mt-4 inline-flex w-full items-center justify-center gap-2 rounded-2xl border border-slate-200 px-4 py-2 text-sm font-medium text-slate-700 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981]"
|
||||
>
|
||||
View full profile
|
||||
<ArrowRight className="h-4 w-4" />
|
||||
@@ -321,7 +321,7 @@ export default function MyPortalPage() {
|
||||
</div>
|
||||
<Link
|
||||
to="/billing"
|
||||
className="inline-flex items-center gap-1 text-sm font-medium text-[#33578D] transition hover:underline"
|
||||
className="inline-flex items-center gap-1 text-sm font-medium text-[#10B981] transition hover:underline"
|
||||
>
|
||||
View all
|
||||
<ArrowRight className="h-4 w-4" />
|
||||
@@ -337,10 +337,10 @@ export default function MyPortalPage() {
|
||||
{recentInvoices.map((invoice) => (
|
||||
<div
|
||||
key={invoice.id}
|
||||
className="rounded-2xl border border-slate-100 p-4 transition hover:border-[#33578D]/20 hover:bg-[#33578D]/5"
|
||||
className="rounded-2xl border border-slate-100 p-4 transition hover:border-[#10B981]/20 hover:bg-[#10B981]/5"
|
||||
>
|
||||
<div className="flex items-center justify-between">
|
||||
<Receipt className="h-4 w-4 text-[#33578D]" />
|
||||
<Receipt className="h-4 w-4 text-[#10B981]" />
|
||||
<InvoiceBadge status={invoice.status} />
|
||||
</div>
|
||||
<p className="mt-2 text-xs text-slate-500">
|
||||
@@ -381,7 +381,7 @@ function KpiCard({
|
||||
const iconWrap =
|
||||
tone === "danger"
|
||||
? "bg-red-100 text-red-600"
|
||||
: "bg-[#33578D]/10 text-[#33578D]";
|
||||
: "bg-[#10B981] text-white";
|
||||
|
||||
const inner = (
|
||||
<div className="flex items-start justify-between">
|
||||
@@ -399,7 +399,7 @@ function KpiCard({
|
||||
);
|
||||
|
||||
const className =
|
||||
"rounded-3xl bg-white p-6 shadow-sm transition hover:shadow-md hover:ring-1 hover:ring-[#33578D]/20";
|
||||
"rounded-3xl bg-white p-6 shadow-sm transition hover:shadow-md hover:ring-1 hover:ring-[#10B981]/20";
|
||||
|
||||
return href ? (
|
||||
<Link to={href} className={`block ${className}`}>
|
||||
@@ -421,7 +421,7 @@ function ProfileRow({
|
||||
}) {
|
||||
return (
|
||||
<div className="flex items-start gap-3">
|
||||
<div className="mt-0.5 text-[#33578D]">{icon}</div>
|
||||
<div className="mt-0.5 text-[#10B981]">{icon}</div>
|
||||
<div className="flex-1">
|
||||
<p className="text-xs font-medium text-slate-500">{label}</p>
|
||||
<p className="mt-0.5 text-sm text-slate-900">{value}</p>
|
||||
|
||||
@@ -34,7 +34,7 @@ export interface NewShipmentPageProps {
|
||||
}
|
||||
|
||||
const selectClass =
|
||||
"flex h-10 w-full rounded-md border border-slate-200 bg-white px-3 py-2 text-sm text-slate-700 shadow-xs outline-none transition hover:border-slate-300 focus:border-[#33578D]/50 focus:ring-2 focus:ring-[#33578D]/20";
|
||||
"flex h-10 w-full rounded-md border border-slate-200 bg-white px-3 py-2 text-sm text-slate-700 shadow-xs outline-none transition hover:border-slate-300 focus:border-[#10B981]/50 focus:ring-2 focus:ring-[#10B981]/20";
|
||||
|
||||
export default function NewShipmentPage({
|
||||
mode = "create",
|
||||
@@ -164,7 +164,7 @@ export default function NewShipmentPage({
|
||||
|
||||
<div className="flex justify-end gap-3">
|
||||
<Button variant="outline">Cancel</Button>
|
||||
<Button className="bg-[#33578D] text-white hover:bg-[#33578D]/90">
|
||||
<Button className="bg-[#10B981] text-white hover:bg-[#10B981]/90">
|
||||
{submitLabel}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -75,14 +75,14 @@ export default function TrackingPage() {
|
||||
value={query}
|
||||
onChange={(e) => setQuery(e.target.value)}
|
||||
placeholder="Search shipments..."
|
||||
className="h-10 w-full rounded-2xl border border-slate-200 bg-white pl-10 pr-4 text-sm text-slate-700 outline-none transition placeholder:text-slate-400 focus:border-[#33578D]/50 focus:ring-2 focus:ring-[#33578D]/20"
|
||||
className="h-10 w-full rounded-2xl border border-slate-200 bg-white pl-10 pr-4 text-sm text-slate-700 outline-none transition placeholder:text-slate-400 focus:border-[#10B981]/50 focus:ring-2 focus:ring-[#10B981]/20"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<NewShipmentPage>
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex items-center justify-center gap-2 rounded-2xl bg-[#33578D] px-4 py-2 text-sm font-medium text-white transition hover:bg-[#33578D]/90"
|
||||
className="inline-flex items-center justify-center gap-2 rounded-2xl bg-[#10B981] px-4 py-2 text-sm font-medium text-white transition hover:bg-[#10B981]/90"
|
||||
>
|
||||
<Plus className="h-4 w-4" />
|
||||
New Shipment
|
||||
@@ -107,8 +107,8 @@ export default function TrackingPage() {
|
||||
onClick={() => setFilter(f)}
|
||||
className={
|
||||
isActive
|
||||
? "inline-flex items-center gap-2 rounded-2xl bg-[#33578D] px-4 py-2 text-sm font-medium text-white"
|
||||
: "inline-flex items-center gap-2 rounded-2xl px-4 py-2 text-sm font-medium text-slate-600 transition hover:bg-[#33578D]/10 hover:text-[#33578D]"
|
||||
? "inline-flex items-center gap-2 rounded-2xl bg-[#10B981] px-4 py-2 text-sm font-medium text-white"
|
||||
: "inline-flex items-center gap-2 rounded-2xl px-4 py-2 text-sm font-medium text-slate-600 transition hover:bg-[#10B981]/10 hover:text-[#10B981]"
|
||||
}
|
||||
>
|
||||
{f}
|
||||
@@ -186,8 +186,8 @@ function ViewToggleButton({
|
||||
aria-pressed={active}
|
||||
className={
|
||||
active
|
||||
? "inline-flex items-center gap-2 rounded-lg bg-white px-3 py-1.5 text-sm font-medium text-[#33578D] shadow-sm"
|
||||
: "inline-flex items-center gap-2 rounded-lg px-3 py-1.5 text-sm font-medium text-slate-600 transition hover:text-[#33578D]"
|
||||
? "inline-flex items-center gap-2 rounded-lg bg-white px-3 py-1.5 text-sm font-medium text-[#10B981] shadow-sm"
|
||||
: "inline-flex items-center gap-2 rounded-lg px-3 py-1.5 text-sm font-medium text-slate-600 transition hover:text-[#10B981]"
|
||||
}
|
||||
>
|
||||
{children}
|
||||
@@ -197,7 +197,7 @@ function ViewToggleButton({
|
||||
|
||||
function ShipmentCard({ shipment }: { shipment: Shipment }) {
|
||||
return (
|
||||
<div className="flex flex-col gap-4 rounded-3xl bg-white p-5 shadow-sm transition hover:shadow-md hover:ring-1 hover:ring-[#33578D]/20">
|
||||
<div className="flex flex-col gap-4 rounded-3xl bg-white p-5 shadow-sm transition hover:shadow-md hover:ring-1 hover:ring-[#10B981]/20">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex flex-col gap-0.5">
|
||||
<span className="text-base font-bold text-slate-900">
|
||||
@@ -211,7 +211,7 @@ function ShipmentCard({ shipment }: { shipment: Shipment }) {
|
||||
</div>
|
||||
|
||||
{/* Route */}
|
||||
<div className="flex items-center justify-between rounded-2xl bg-[#33578D]/5 p-3">
|
||||
<div className="flex items-center justify-between rounded-2xl bg-[#10B981]/5 p-3">
|
||||
<div className="text-sm">
|
||||
<p className="text-xs font-medium uppercase tracking-wide text-slate-500">
|
||||
From
|
||||
@@ -220,7 +220,7 @@ function ShipmentCard({ shipment }: { shipment: Shipment }) {
|
||||
{shipment.originStation}
|
||||
</p>
|
||||
</div>
|
||||
<ArrowRight className="h-5 w-5 text-[#33578D]" />
|
||||
<ArrowRight className="h-5 w-5 text-[#10B981]" />
|
||||
<div className="text-sm text-right">
|
||||
<p className="text-xs font-medium uppercase tracking-wide text-slate-500">
|
||||
To
|
||||
@@ -241,7 +241,7 @@ function ShipmentCard({ shipment }: { shipment: Shipment }) {
|
||||
</div>
|
||||
<div className="h-1.5 w-full overflow-hidden rounded-full bg-slate-100">
|
||||
<div
|
||||
className="h-full rounded-full bg-[#33578D] transition-all"
|
||||
className="h-full rounded-full bg-[#10B981] transition-all"
|
||||
style={{ width: `${shipment.progress}%` }}
|
||||
/>
|
||||
</div>
|
||||
@@ -250,7 +250,7 @@ function ShipmentCard({ shipment }: { shipment: Shipment }) {
|
||||
{/* Meta */}
|
||||
<div className="space-y-2 text-sm text-slate-700">
|
||||
<div className="flex items-center gap-2">
|
||||
<Building2 className="h-4 w-4 text-[#33578D]" />
|
||||
<Building2 className="h-4 w-4 text-[#10B981]" />
|
||||
<span>{shipment.customer}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
@@ -258,7 +258,7 @@ function ShipmentCard({ shipment }: { shipment: Shipment }) {
|
||||
<span className="capitalize">{shipment.mode}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<MapPin className="h-4 w-4 text-[#33578D]" />
|
||||
<MapPin className="h-4 w-4 text-[#10B981]" />
|
||||
<span>{shipment.currentLocation}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 text-xs text-slate-500">
|
||||
@@ -286,7 +286,7 @@ function ShipmentCard({ shipment }: { shipment: Shipment }) {
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex items-center gap-1 rounded-xl border border-slate-200 px-3 py-1.5 text-xs font-medium text-slate-600 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D]"
|
||||
className="inline-flex items-center gap-1 rounded-xl border border-slate-200 px-3 py-1.5 text-xs font-medium text-slate-600 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981]"
|
||||
>
|
||||
<Pencil className="h-3.5 w-3.5" />
|
||||
Edit
|
||||
@@ -330,11 +330,11 @@ function ShipmentTable({ shipments: rows }: { shipments: Shipment[] }) {
|
||||
{rows.map((shipment) => (
|
||||
<tr
|
||||
key={shipment.id}
|
||||
className="border-t border-slate-100 transition hover:bg-[#33578D]/5"
|
||||
className="border-t border-slate-100 transition hover:bg-[#10B981]/5"
|
||||
>
|
||||
<td className="px-6 py-4">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-[#33578D]/10 text-[#33578D]">
|
||||
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-[#10B981] text-white">
|
||||
<Truck className="h-5 w-5" />
|
||||
</div>
|
||||
<div>
|
||||
@@ -375,7 +375,7 @@ function ShipmentTable({ shipments: rows }: { shipments: Shipment[] }) {
|
||||
<div className="flex w-32 items-center gap-2">
|
||||
<div className="h-1.5 flex-1 overflow-hidden rounded-full bg-slate-100">
|
||||
<div
|
||||
className="h-full rounded-full bg-[#33578D]"
|
||||
className="h-full rounded-full bg-[#10B981]"
|
||||
style={{ width: `${shipment.progress}%` }}
|
||||
/>
|
||||
</div>
|
||||
@@ -387,7 +387,7 @@ function ShipmentTable({ shipments: rows }: { shipments: Shipment[] }) {
|
||||
|
||||
<td className="px-6 py-4 text-sm text-slate-700">
|
||||
<div className="flex items-center gap-1.5">
|
||||
<MapPin className="h-3.5 w-3.5 text-[#33578D]" />
|
||||
<MapPin className="h-3.5 w-3.5 text-[#10B981]" />
|
||||
{shipment.currentLocation}
|
||||
</div>
|
||||
</td>
|
||||
@@ -413,7 +413,7 @@ function ShipmentTable({ shipments: rows }: { shipments: Shipment[] }) {
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
className="rounded-xl border border-slate-200 p-2 text-slate-600 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D]"
|
||||
className="rounded-xl border border-slate-200 p-2 text-slate-600 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981]"
|
||||
>
|
||||
<Pencil className="h-4 w-4" />
|
||||
</button>
|
||||
@@ -441,9 +441,9 @@ function ShipmentTable({ shipments: rows }: { shipments: Shipment[] }) {
|
||||
}
|
||||
|
||||
function ModeIcon({ mode }: { mode: ShipmentMode }) {
|
||||
if (mode === "rail") return <Train className="h-4 w-4 text-[#33578D]" />;
|
||||
if (mode === "truck") return <Truck className="h-4 w-4 text-[#33578D]" />;
|
||||
return <Train className="h-4 w-4 text-[#33578D]" />;
|
||||
if (mode === "rail") return <Train className="h-4 w-4 text-[#10B981]" />;
|
||||
if (mode === "truck") return <Truck className="h-4 w-4 text-[#10B981]" />;
|
||||
return <Train className="h-4 w-4 text-[#10B981]" />;
|
||||
}
|
||||
|
||||
function StatusBadge({ status }: { status: ShipmentStatus }) {
|
||||
|
||||
@@ -45,7 +45,7 @@ export interface NewTrainPageProps {
|
||||
}
|
||||
|
||||
const selectClass =
|
||||
"flex h-10 w-full rounded-md border border-slate-200 bg-white px-3 py-2 text-sm text-slate-700 shadow-xs outline-none transition hover:border-slate-300 focus:border-[#33578D]/50 focus:ring-2 focus:ring-[#33578D]/20";
|
||||
"flex h-10 w-full rounded-md border border-slate-200 bg-white px-3 py-2 text-sm text-slate-700 shadow-xs outline-none transition hover:border-slate-300 focus:border-[#10B981]/50 focus:ring-2 focus:ring-[#10B981]/20";
|
||||
|
||||
export default function NewTrainPage({
|
||||
mode = "create",
|
||||
@@ -230,7 +230,7 @@ export default function NewTrainPage({
|
||||
|
||||
<div className="flex justify-end gap-3">
|
||||
<Button variant="outline">Cancel</Button>
|
||||
<Button className="bg-[#33578D] text-white hover:bg-[#33578D]/90">
|
||||
<Button className="bg-[#10B981] text-white hover:bg-[#10B981]/90">
|
||||
{submitLabel}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -93,14 +93,14 @@ export default function TrainsPage() {
|
||||
setPage(1);
|
||||
}}
|
||||
placeholder="Search trains..."
|
||||
className="h-10 w-full rounded-2xl border border-slate-200 bg-white pl-10 pr-4 text-sm text-slate-700 outline-none transition placeholder:text-slate-400 focus:border-[#33578D]/50 focus:ring-2 focus:ring-[#33578D]/20"
|
||||
className="h-10 w-full rounded-2xl border border-slate-200 bg-white pl-10 pr-4 text-sm text-slate-700 outline-none transition placeholder:text-slate-400 focus:border-[#10B981]/50 focus:ring-2 focus:ring-[#10B981]/20"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<NewTrainPage>
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex items-center justify-center gap-2 rounded-2xl bg-[#33578D] px-4 py-2 text-sm font-medium text-white transition hover:bg-[#33578D]/90"
|
||||
className="inline-flex items-center justify-center gap-2 rounded-2xl bg-[#10B981] px-4 py-2 text-sm font-medium text-white transition hover:bg-[#10B981]/90"
|
||||
>
|
||||
<Plus className="h-4 w-4" />
|
||||
New Train
|
||||
@@ -147,8 +147,8 @@ export default function TrainsPage() {
|
||||
}}
|
||||
className={
|
||||
isActive
|
||||
? "inline-flex items-center gap-2 rounded-2xl bg-[#33578D] px-4 py-2 text-sm font-medium text-white"
|
||||
: "inline-flex items-center gap-2 rounded-2xl px-4 py-2 text-sm font-medium text-slate-600 transition hover:bg-[#33578D]/10 hover:text-[#33578D]"
|
||||
? "inline-flex items-center gap-2 rounded-2xl bg-[#10B981] px-4 py-2 text-sm font-medium text-white"
|
||||
: "inline-flex items-center gap-2 rounded-2xl px-4 py-2 text-sm font-medium text-slate-600 transition hover:bg-[#10B981]/10 hover:text-[#10B981]"
|
||||
}
|
||||
>
|
||||
{f}
|
||||
@@ -179,7 +179,7 @@ export default function TrainsPage() {
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<button className="inline-flex items-center gap-2 rounded-2xl border border-slate-200 px-4 py-2 text-sm font-medium text-slate-700 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D]">
|
||||
<button className="inline-flex items-center gap-2 rounded-2xl border border-slate-200 px-4 py-2 text-sm font-medium text-slate-700 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981]">
|
||||
<Filter className="h-4 w-4" />
|
||||
Filter
|
||||
</button>
|
||||
@@ -213,11 +213,11 @@ export default function TrainsPage() {
|
||||
paginated.map((train) => (
|
||||
<tr
|
||||
key={train.id}
|
||||
className="border-t border-slate-100 transition hover:bg-[#33578D]/5"
|
||||
className="border-t border-slate-100 transition hover:bg-[#10B981]/5"
|
||||
>
|
||||
<td className="px-6 py-4">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-[#33578D]/10 text-[#33578D]">
|
||||
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-[#10B981] text-white">
|
||||
<TrainIcon className="h-5 w-5" />
|
||||
</div>
|
||||
<div>
|
||||
@@ -272,7 +272,7 @@ export default function TrainsPage() {
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
className="rounded-xl border border-slate-200 p-2 text-slate-600 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D]"
|
||||
className="rounded-xl border border-slate-200 p-2 text-slate-600 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981]"
|
||||
>
|
||||
<Pencil className="h-4 w-4" />
|
||||
</button>
|
||||
@@ -345,7 +345,7 @@ function Pagination({
|
||||
id="train-page-size"
|
||||
value={pageSize}
|
||||
onChange={(e) => onPageSizeChange(Number(e.target.value))}
|
||||
className="h-9 rounded-xl border border-slate-200 bg-white px-3 text-sm text-slate-700 outline-none transition focus:border-[#33578D]/50 focus:ring-2 focus:ring-[#33578D]/20"
|
||||
className="h-9 rounded-xl border border-slate-200 bg-white px-3 text-sm text-slate-700 outline-none transition focus:border-[#10B981]/50 focus:ring-2 focus:ring-[#10B981]/20"
|
||||
>
|
||||
{PAGE_SIZE_OPTIONS.map((size) => (
|
||||
<option key={size} value={size}>
|
||||
@@ -363,7 +363,7 @@ function Pagination({
|
||||
type="button"
|
||||
onClick={() => onPageChange(page - 1)}
|
||||
disabled={page <= 1}
|
||||
className="inline-flex h-9 items-center gap-1 rounded-xl border border-slate-200 px-3 text-sm font-medium text-slate-700 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D] disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent disabled:hover:text-slate-700"
|
||||
className="inline-flex h-9 items-center gap-1 rounded-xl border border-slate-200 px-3 text-sm font-medium text-slate-700 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981] disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent disabled:hover:text-slate-700"
|
||||
>
|
||||
<ChevronLeft className="h-4 w-4" />
|
||||
Prev
|
||||
@@ -379,8 +379,8 @@ function Pagination({
|
||||
aria-current={isActive ? "page" : undefined}
|
||||
className={
|
||||
isActive
|
||||
? "h-9 w-9 rounded-xl bg-[#33578D] text-sm font-medium text-white"
|
||||
: "h-9 w-9 rounded-xl border border-slate-200 text-sm font-medium text-slate-700 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D]"
|
||||
? "h-9 w-9 rounded-xl bg-[#10B981] text-sm font-medium text-white"
|
||||
: "h-9 w-9 rounded-xl border border-slate-200 text-sm font-medium text-slate-700 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981]"
|
||||
}
|
||||
>
|
||||
{p}
|
||||
@@ -392,7 +392,7 @@ function Pagination({
|
||||
type="button"
|
||||
onClick={() => onPageChange(page + 1)}
|
||||
disabled={page >= totalPages}
|
||||
className="inline-flex h-9 items-center gap-1 rounded-xl border border-slate-200 px-3 text-sm font-medium text-slate-700 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D] disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent disabled:hover:text-slate-700"
|
||||
className="inline-flex h-9 items-center gap-1 rounded-xl border border-slate-200 px-3 text-sm font-medium text-slate-700 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981] disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent disabled:hover:text-slate-700"
|
||||
>
|
||||
Next
|
||||
<ChevronRight className="h-4 w-4" />
|
||||
@@ -412,13 +412,13 @@ function StatCard({
|
||||
icon: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<div className="rounded-3xl bg-white p-6 shadow-sm transition hover:shadow-md hover:ring-1 hover:ring-[#33578D]/20">
|
||||
<div className="rounded-3xl bg-white p-6 shadow-sm transition hover:shadow-md hover:ring-1 hover:ring-[#10B981]/20">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm text-slate-500">{title}</p>
|
||||
<h3 className="mt-2 text-3xl font-bold text-slate-900">{value}</h3>
|
||||
</div>
|
||||
<div className="flex h-12 w-12 items-center justify-center rounded-2xl bg-[#33578D]/10 text-[#33578D]">
|
||||
<div className="flex h-12 w-12 items-center justify-center rounded-2xl bg-[#10B981] text-white">
|
||||
{icon}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -37,7 +37,7 @@ function getInitialTheme(): Theme {
|
||||
}
|
||||
|
||||
const iconButtonClass =
|
||||
"inline-flex h-10 w-10 items-center justify-center rounded-xl border border-slate-200 text-slate-600 transition hover:border-[#33578D]/30 hover:bg-[#33578D]/10 hover:text-[#33578D] dark:border-slate-700 dark:text-slate-300 dark:hover:border-[#33578D]/40 dark:hover:bg-[#33578D]/20 dark:hover:text-white";
|
||||
"inline-flex h-10 w-10 items-center justify-center rounded-xl border border-slate-200 text-slate-600 transition hover:border-[#10B981]/30 hover:bg-[#10B981]/10 hover:text-[#10B981] dark:border-slate-700 dark:text-slate-300 dark:hover:border-[#10B981]/40 dark:hover:bg-[#10B981]/20 dark:hover:text-white";
|
||||
|
||||
const DashboardLayout = ({
|
||||
title,
|
||||
@@ -112,7 +112,7 @@ const DashboardLayout = ({
|
||||
aria-label={
|
||||
theme === "dark" ? "Switch to light mode" : "Switch to dark mode"
|
||||
}
|
||||
className="inline-flex h-8 w-8 items-center justify-center rounded-lg text-slate-600 transition hover:bg-[#33578D]/10 hover:text-[#33578D] dark:text-slate-300 dark:hover:bg-[#33578D]/20 dark:hover:text-white"
|
||||
className="inline-flex h-8 w-8 items-center justify-center rounded-lg text-slate-600 transition hover:bg-[#10B981]/10 hover:text-[#10B981] dark:text-slate-300 dark:hover:bg-[#10B981]/20 dark:hover:text-white"
|
||||
>
|
||||
{theme === "dark" ? (
|
||||
<Sun className="h-4 w-4" />
|
||||
@@ -161,9 +161,9 @@ const DashboardLayout = ({
|
||||
aria-haspopup="menu"
|
||||
aria-expanded={isUserMenuOpen}
|
||||
onClick={() => setIsUserMenuOpen((open) => !open)}
|
||||
className="flex items-center gap-2 rounded-xl border border-transparent px-2 py-1.5 transition hover:border-[#33578D]/20 hover:bg-[#33578D]/5 aria-expanded:border-[#33578D]/30 aria-expanded:bg-[#33578D]/10 dark:hover:border-[#33578D]/30 dark:hover:bg-[#33578D]/10 dark:aria-expanded:border-[#33578D]/40 dark:aria-expanded:bg-[#33578D]/20"
|
||||
className="flex items-center gap-2 rounded-xl border border-transparent px-2 py-1.5 transition hover:border-[#10B981]/20 hover:bg-[#10B981]/5 aria-expanded:border-[#10B981]/30 aria-expanded:bg-[#10B981]/10 dark:hover:border-[#10B981]/30 dark:hover:bg-[#10B981]/10 dark:aria-expanded:border-[#10B981]/40 dark:aria-expanded:bg-[#10B981]/20"
|
||||
>
|
||||
<div className="flex h-8 w-8 items-center justify-center rounded-full bg-[#33578D] text-xs font-semibold text-white">
|
||||
<div className="flex h-8 w-8 items-center justify-center rounded-full bg-[#10B981] text-xs font-semibold text-white">
|
||||
{initials}
|
||||
</div>
|
||||
<span className="hidden text-sm font-medium text-slate-700 md:block dark:text-slate-200">
|
||||
@@ -171,7 +171,7 @@ const DashboardLayout = ({
|
||||
</span>
|
||||
<ChevronDown
|
||||
className={`h-4 w-4 text-slate-400 transition dark:text-slate-500 ${
|
||||
isUserMenuOpen ? "rotate-180 text-[#33578D]" : ""
|
||||
isUserMenuOpen ? "rotate-180 text-[#10B981]" : ""
|
||||
}`}
|
||||
/>
|
||||
</button>
|
||||
@@ -195,7 +195,7 @@ const DashboardLayout = ({
|
||||
href="#profile"
|
||||
role="menuitem"
|
||||
onClick={() => setIsUserMenuOpen(false)}
|
||||
className="flex items-center gap-2 px-4 py-2 text-sm text-slate-700 transition hover:bg-[#33578D]/10 hover:text-[#33578D] dark:text-slate-300 dark:hover:bg-[#33578D]/20 dark:hover:text-white"
|
||||
className="flex items-center gap-2 px-4 py-2 text-sm text-slate-700 transition hover:bg-[#10B981]/10 hover:text-[#10B981] dark:text-slate-300 dark:hover:bg-[#10B981]/20 dark:hover:text-white"
|
||||
>
|
||||
<User className="h-4 w-4" />
|
||||
Profile
|
||||
|
||||
@@ -15,6 +15,12 @@ export interface SidebarProps {
|
||||
headerExtra?: ReactNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Brand palette
|
||||
* #10B981 — dominant dark green → brand mark, active state, hover text
|
||||
* #10B981 — secondary green → hover background tint
|
||||
* #10B981 — muted green tone → sidebar canvas
|
||||
*/
|
||||
const Sidebar = ({
|
||||
title,
|
||||
items,
|
||||
@@ -22,11 +28,11 @@ const Sidebar = ({
|
||||
onNavigate,
|
||||
headerExtra,
|
||||
}: SidebarProps) => (
|
||||
<aside className="flex h-full w-64 shrink-0 flex-col gap-1 overflow-y-auto border-r border-slate-200 bg-[#33578D]/10 px-3 py-5 dark:border-slate-800 dark:bg-slate-900">
|
||||
<aside className="flex h-full w-64 shrink-0 flex-col gap-1 overflow-y-auto border-r border-slate-200 bg-[#10B981]/10 px-3 py-5 dark:border-slate-800 dark:bg-slate-900">
|
||||
{title ? (
|
||||
<div className="flex items-center justify-between gap-2 px-3 pb-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex h-9 w-9 items-center justify-center rounded-xl bg-[#33578D] text-sm font-bold text-white">
|
||||
<div className="flex h-9 w-9 items-center justify-center rounded-xl bg-[#10B981] text-sm font-bold text-white">
|
||||
{title.charAt(0)}
|
||||
</div>
|
||||
<div className="text-base font-semibold text-slate-800 dark:text-slate-100">
|
||||
@@ -56,8 +62,8 @@ const Sidebar = ({
|
||||
className={clsx(
|
||||
"group flex items-center gap-3 rounded-xl px-3 py-2.5 text-sm font-medium transition",
|
||||
isActive
|
||||
? "bg-[#33578D] text-white shadow-sm shadow-[#33578D]/20"
|
||||
: "text-slate-700 hover:bg-[#33578D]/10 hover:text-[#33578D] dark:text-slate-300 dark:hover:bg-[#33578D]/20 dark:hover:text-white",
|
||||
? "bg-[#10B981] text-white shadow-sm shadow-[#10B981]/25"
|
||||
: "text-slate-700 hover:bg-[#10B981]/10 hover:text-[#10B981] dark:text-slate-300 dark:hover:bg-[#10B981]/20 dark:hover:text-white",
|
||||
)}
|
||||
>
|
||||
{item.icon ? (
|
||||
@@ -66,7 +72,7 @@ const Sidebar = ({
|
||||
"flex h-5 w-5 items-center justify-center [&_svg]:h-5 [&_svg]:w-5",
|
||||
isActive
|
||||
? "text-white"
|
||||
: "text-slate-500 group-hover:text-[#33578D] dark:text-slate-400 dark:group-hover:text-white",
|
||||
: "text-slate-500 group-hover:text-[#10B981] dark:text-slate-400 dark:group-hover:text-white",
|
||||
)}
|
||||
>
|
||||
{item.icon}
|
||||
|
||||
Reference in New Issue
Block a user