merged code with dev
This commit is contained in:
Generated
+14
@@ -8,6 +8,7 @@
|
||||
"name": "@aeroresolve/frontend",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@phosphor-icons/react": "^2.1.10",
|
||||
"@tailwindcss/vite": "^4.3.0",
|
||||
"axios": "^1.18.1",
|
||||
"framer-motion": "^12.40.0",
|
||||
@@ -576,6 +577,19 @@
|
||||
"url": "https://github.com/sponsors/Boshen"
|
||||
}
|
||||
},
|
||||
"node_modules/@phosphor-icons/react": {
|
||||
"version": "2.1.10",
|
||||
"resolved": "https://registry.npmjs.org/@phosphor-icons/react/-/react-2.1.10.tgz",
|
||||
"integrity": "sha512-vt8Tvq8GLjheAZZYa+YG/pW7HDbov8El/MANW8pOAz4eGxrwhnbfrQZq0Cp4q8zBEu8NIhHdnr+r8thnfRSNYA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">= 16.8",
|
||||
"react-dom": ">= 16.8"
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-android-arm64": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.1.0.tgz",
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
"preview:uat": "vite preview --mode uat"
|
||||
},
|
||||
"dependencies": {
|
||||
"@phosphor-icons/react": "^2.1.10",
|
||||
"@tailwindcss/vite": "^4.3.0",
|
||||
"axios": "^1.18.1",
|
||||
"framer-motion": "^12.40.0",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useState, useEffect, useMemo, useRef } from 'react';
|
||||
import { FileText, ChevronRight, ChevronLeft, User, CircleCheck, Globe } from 'lucide-react';
|
||||
import { FileTextIcon, CaretRightIcon, CaretLeftIcon, UserListIcon, GlobeIcon, UserCircleCheckIcon } from '@phosphor-icons/react';
|
||||
import {
|
||||
CustomModal,
|
||||
CustomInput,
|
||||
@@ -344,13 +344,13 @@ export default function AddCohart({ isOpen, onClose, onSuccess, editData }: AddC
|
||||
Cancel
|
||||
</CustomButton>
|
||||
) : (
|
||||
<CustomButton variant="outlined" leftIcon={<ChevronLeft size={18} />} onClick={() => setStep(1)}>
|
||||
<CustomButton variant="outlined" leftIcon={<CaretLeftIcon size={18} />} onClick={() => setStep(1)}>
|
||||
Previous Step
|
||||
</CustomButton>
|
||||
)}
|
||||
<CustomButton
|
||||
variant="primary"
|
||||
rightIcon={step === 2 && isOnFinalSection ? undefined : <ChevronRight size={18} />}
|
||||
rightIcon={step === 2 && isOnFinalSection ? undefined : <CaretRightIcon size={18} />}
|
||||
onClick={
|
||||
step === 1
|
||||
? () => setStep(2)
|
||||
@@ -377,7 +377,7 @@ export default function AddCohart({ isOpen, onClose, onSuccess, editData }: AddC
|
||||
className="!max-w-[750px]"
|
||||
title={isEditMode ? 'Edit Cohort' : 'New Dynamic Cohorts'}
|
||||
description="Configure targeting criteria for high-precision recovery."
|
||||
icon={<FileText size={20} />}
|
||||
icon={<FileTextIcon size={20} />}
|
||||
headerExtra={stepper}
|
||||
footer={footer}
|
||||
allowBackdropClose={false}
|
||||
@@ -442,7 +442,7 @@ export default function AddCohart({ isOpen, onClose, onSuccess, editData }: AddC
|
||||
|
||||
{/* Passenger Attributes */}
|
||||
<CustomAccordionSection
|
||||
icon={<User size={15} className="text-gray-700" strokeWidth={2} />}
|
||||
icon={<UserListIcon size={15} className="text-gray-700" strokeWidth={2} />}
|
||||
title="Passenger Attributes"
|
||||
isOpen={openSection === 'passenger'}
|
||||
hasData={passengerHasData}
|
||||
@@ -478,7 +478,7 @@ export default function AddCohart({ isOpen, onClose, onSuccess, editData }: AddC
|
||||
|
||||
{/* Customer Value */}
|
||||
<CustomAccordionSection
|
||||
icon={<CircleCheck size={15} className="text-gray-700" strokeWidth={2} />}
|
||||
icon={<UserCircleCheckIcon size={15} className="text-gray-700" />}
|
||||
title="Customer Value"
|
||||
isOpen={openSection === 'customer'}
|
||||
hasData={customerHasData}
|
||||
@@ -523,7 +523,7 @@ export default function AddCohart({ isOpen, onClose, onSuccess, editData }: AddC
|
||||
|
||||
{/* Journey Context */}
|
||||
<CustomAccordionSection
|
||||
icon={<Globe size={15} className="text-gray-700" strokeWidth={2} />}
|
||||
icon={<GlobeIcon size={15} className="text-gray-700" strokeWidth={2} />}
|
||||
title="Journey Context"
|
||||
isOpen={openSection === 'journey'}
|
||||
hasData={journeyHasData}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import AddCohart from './AddCohart';
|
||||
import { Plus, Trash2, Search, Check, X, Pencil } from 'lucide-react';
|
||||
import { PlusIcon, TrashIcon, MagnifyingGlassIcon, CheckIcon, XIcon, PencilSimpleIcon } from '@phosphor-icons/react';
|
||||
import {
|
||||
CustomTable,
|
||||
CustomInput,
|
||||
@@ -174,7 +174,7 @@ export default function CohortList() {
|
||||
<CustomActionMenu>
|
||||
{row.status !== 'Active' && (
|
||||
<CustomActionItem
|
||||
icon={<Check size={15} />}
|
||||
icon={<CheckIcon size={15} />}
|
||||
variant="success"
|
||||
onClick={() => setDeactivateTarget(row)}
|
||||
>
|
||||
@@ -183,20 +183,20 @@ export default function CohortList() {
|
||||
)}
|
||||
{row.status === 'Active' && (
|
||||
<CustomActionItem
|
||||
icon={<X size={15} />}
|
||||
icon={<XIcon size={15} />}
|
||||
onClick={() => setDeactivateTarget(row)}
|
||||
>
|
||||
Deactivate
|
||||
</CustomActionItem>
|
||||
)}
|
||||
<CustomActionItem
|
||||
icon={<Pencil size={15} />}
|
||||
icon={<PencilSimpleIcon size={15} />}
|
||||
onClick={() => setEditTarget(row)}
|
||||
>
|
||||
Edit
|
||||
</CustomActionItem>
|
||||
<CustomActionItem
|
||||
icon={<Trash2 size={15} />}
|
||||
icon={<TrashIcon size={15} />}
|
||||
variant="danger"
|
||||
onClick={() => setDeleteTarget(row)}
|
||||
>
|
||||
@@ -249,7 +249,7 @@ export default function CohortList() {
|
||||
placeholder="Search cohorts..."
|
||||
value={search}
|
||||
onChange={e => handleSearchChange(e.target.value)}
|
||||
leftIcon={<Search size={16} />}
|
||||
leftIcon={<MagnifyingGlassIcon size={16} />}
|
||||
className="!bg-[#F3F6F5] !rounded-[10px] !h-[38px] !border !border-[#E5E7EB]"
|
||||
containerClassName="!gap-0"
|
||||
/>
|
||||
@@ -269,7 +269,7 @@ export default function CohortList() {
|
||||
<CustomButton
|
||||
variant="primary"
|
||||
size="md"
|
||||
leftIcon={<Plus size={16} />}
|
||||
leftIcon={<PlusIcon size={16} />}
|
||||
className="!rounded-[10px] !gap-[10px] !h-[40px]"
|
||||
onClick={() => setIsAddOpen(true)}
|
||||
>
|
||||
|
||||
@@ -12,7 +12,7 @@ import CustomRadio from "../../components/custom/CustomRadio";
|
||||
import CustomSwitch from "../../components/custom/CustomSwitch";
|
||||
import CustomTable, { type Column } from "../../components/custom/CustomTable";
|
||||
import CustomActionMenu, { CustomActionItem } from "../../components/custom/CustomActionMenu";
|
||||
import { FileText, ChevronRight, Plus, Check, X, Copy, Edit2, Trash2 } from "lucide-react";
|
||||
import { FileTextIcon, CaretRightIcon, CheckIcon, XIcon, CopyIcon, PencilSimpleIcon, TrashIcon, PlusIcon } from "@phosphor-icons/react";
|
||||
|
||||
function HomePage() {
|
||||
const [searchValue, setSearchValue] = useState("");
|
||||
@@ -76,11 +76,11 @@ function HomePage() {
|
||||
accessor: () => (
|
||||
<div className="flex justify-center w-full">
|
||||
<CustomActionMenu>
|
||||
<CustomActionItem variant="success" icon={<Check size={16} />}>Activate</CustomActionItem>
|
||||
<CustomActionItem icon={<X size={16} />}>Deactivate</CustomActionItem>
|
||||
<CustomActionItem icon={<Copy size={16} />}>Duplicate</CustomActionItem>
|
||||
<CustomActionItem icon={<Edit2 size={16} />}>Edit</CustomActionItem>
|
||||
<CustomActionItem variant="danger" icon={<Trash2 size={16} />}>Delete</CustomActionItem>
|
||||
<CustomActionItem variant="success" icon={<CheckIcon size={16} />}>Activate</CustomActionItem>
|
||||
<CustomActionItem icon={<XIcon size={16} />}>Deactivate</CustomActionItem>
|
||||
<CustomActionItem icon={<CopyIcon size={16} />}>Duplicate</CustomActionItem>
|
||||
<CustomActionItem icon={<PencilSimpleIcon size={16} />}>Edit</CustomActionItem>
|
||||
<CustomActionItem variant="danger" icon={<TrashIcon size={16} />}>Delete</CustomActionItem>
|
||||
</CustomActionMenu>
|
||||
</div>
|
||||
),
|
||||
@@ -127,7 +127,7 @@ function HomePage() {
|
||||
size="md"
|
||||
/>
|
||||
</div>
|
||||
<CustomButton variant="primary" size="md" leftIcon={<Plus size={16} />}>
|
||||
<CustomButton variant="primary" size="md" leftIcon={<PlusIcon size={16} />}>
|
||||
Create Cohort
|
||||
</CustomButton>
|
||||
</div>
|
||||
@@ -334,11 +334,11 @@ function HomePage() {
|
||||
onClose={() => setIsModalOpen(false)}
|
||||
title="New Dynamic Cohorts"
|
||||
description="Configure targeting criteria for high-precision recovery."
|
||||
icon={<FileText size={24} />}
|
||||
icon={<FileTextIcon size={24} />}
|
||||
primaryAction={{
|
||||
label: "Next Step",
|
||||
onClick: () => setIsModalOpen(false),
|
||||
icon: <ChevronRight size={18} />
|
||||
icon: <CaretRightIcon size={18} />
|
||||
}}
|
||||
secondaryAction={{
|
||||
label: "Cancel",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useState, useRef, useEffect } from 'react';
|
||||
import {
|
||||
ArrowLeft, Plus, Trash2, Minus, Book, Users, GitBranch, ChevronDown
|
||||
} from 'lucide-react';
|
||||
ArrowLeftIcon, PlusIcon, TrashIcon, MinusIcon, BookIcon, UsersIcon, GitBranchIcon, CaretDownIcon
|
||||
} from '@phosphor-icons/react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import {
|
||||
CustomInput,
|
||||
@@ -128,7 +128,7 @@ function LogicDropdown({ value, onChange, readOnly = false }: { value: string; o
|
||||
className={boxClass}
|
||||
>
|
||||
{value}
|
||||
<ChevronDown size={16} className={`transition-transform duration-200 ${open ? 'rotate-180' : ''}`} />
|
||||
<CaretDownIcon size={16} className={`transition-transform duration-200 ${open ? 'rotate-180' : ''}`} />
|
||||
</button>
|
||||
{open && (
|
||||
<div className="absolute z-20 mt-1 w-full bg-white border border-gray-200 rounded-lg shadow-lg overflow-hidden">
|
||||
@@ -311,7 +311,7 @@ export default function AddPolicyEngine() {
|
||||
onClick={() => navigate('/policy-engine')}
|
||||
className="mt-1 p-1 hover:bg-gray-100 rounded-full transition-colors text-gray-500"
|
||||
>
|
||||
<ArrowLeft size={20} />
|
||||
<ArrowLeftIcon size={20} />
|
||||
</button>
|
||||
<div className="flex flex-col">
|
||||
<h1 className="text-xl font-bold text-[#0F172B]">Deploy New Policy</h1>
|
||||
@@ -322,7 +322,7 @@ export default function AddPolicyEngine() {
|
||||
<CustomButton
|
||||
variant="primary"
|
||||
className="!bg-[#1E7D5C] hover:!bg-[#17664B] !h-10 !px-4 !rounded-[10px]"
|
||||
leftIcon={<Plus size={16} />}
|
||||
leftIcon={<PlusIcon size={16} />}
|
||||
>
|
||||
Deploy Policy
|
||||
</CustomButton>
|
||||
@@ -335,7 +335,7 @@ export default function AddPolicyEngine() {
|
||||
|
||||
{/* Policy Information Card */}
|
||||
<div className="bg-[#FAFAFA] rounded-[16px] p-6 border border-gray-100">
|
||||
<CardHeader icon={Book} title="Policy Information" />
|
||||
<CardHeader icon={BookIcon} title="Policy Information" />
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-6">
|
||||
<div className="flex flex-col gap-2">
|
||||
@@ -396,7 +396,7 @@ export default function AddPolicyEngine() {
|
||||
|
||||
{/* Target Audience Card */}
|
||||
<div className="bg-[#FAFAFA] rounded-[16px] p-6 border border-gray-100">
|
||||
<CardHeader icon={Users} title="Target Audience" />
|
||||
<CardHeader icon={UsersIcon} title="Target Audience" />
|
||||
|
||||
<div className="flex flex-col gap-6">
|
||||
<div className="flex items-center gap-8">
|
||||
@@ -439,7 +439,7 @@ export default function AddPolicyEngine() {
|
||||
{/* Rule Engine Card */}
|
||||
<div className="bg-[#FAFAFA] rounded-[16px] p-6 border border-gray-100">
|
||||
<div className="flex items-center justify-between mb-6">
|
||||
<CardHeader icon={GitBranch} title="Rule Engine" />
|
||||
<CardHeader icon={GitBranchIcon} title="Rule Engine" />
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleAddRule}
|
||||
@@ -451,7 +451,7 @@ export default function AddPolicyEngine() {
|
||||
backgroundClip: 'padding-box, border-box',
|
||||
}}
|
||||
>
|
||||
<Plus size={16} color="#14704E" />
|
||||
<PlusIcon size={16} color="#14704E" />
|
||||
<span className="font-bold text-[14px] leading-none bg-gradient-to-b from-[#1B9869] to-[#14704E] bg-clip-text text-transparent">
|
||||
Add Strategic Rule
|
||||
</span>
|
||||
@@ -470,7 +470,7 @@ export default function AddPolicyEngine() {
|
||||
onClick={() => handleDeleteRule(rule.id)}
|
||||
className="p-1.5 text-red-500 hover:bg-red-50 rounded-md transition-colors"
|
||||
>
|
||||
<Trash2 size={18} />
|
||||
<TrashIcon size={18} />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
@@ -498,7 +498,7 @@ export default function AddPolicyEngine() {
|
||||
disabled={prevPriority === null}
|
||||
className="flex-1 flex items-center justify-center h-full hover:bg-gray-50 text-gray-500 disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:bg-transparent"
|
||||
>
|
||||
<Minus size={16} />
|
||||
<MinusIcon size={16} />
|
||||
</button>
|
||||
<span className="flex-1 text-center text-[14px] font-semibold text-gray-800">
|
||||
{rule.priority}
|
||||
@@ -508,7 +508,7 @@ export default function AddPolicyEngine() {
|
||||
disabled={nextPriority === null}
|
||||
className="flex-1 flex items-center justify-center h-full hover:bg-gray-50 text-gray-500 disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:bg-transparent"
|
||||
>
|
||||
<Plus size={16} />
|
||||
<PlusIcon size={16} />
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
@@ -564,7 +564,7 @@ export default function AddPolicyEngine() {
|
||||
<CustomButton
|
||||
variant="secondary"
|
||||
className="!w-full !justify-center !bg-[#EAFAF5] hover:!bg-[#d9ece4] !px-4 !gap-2.5 !h-[49px] !rounded-[12px] whitespace-nowrap"
|
||||
leftIcon={<Plus size={16} color="#14704E" />}
|
||||
leftIcon={<PlusIcon size={16} color="#14704E" />}
|
||||
onClick={() => handleAddCondition(rule.id)}
|
||||
>
|
||||
<span className="font-bold text-[14px] leading-none text-center bg-gradient-to-b from-[#1B9869] to-[#14704E] bg-clip-text text-transparent">
|
||||
@@ -579,7 +579,7 @@ export default function AddPolicyEngine() {
|
||||
onClick={() => handleDeleteCondition(rule.id, condition.id)}
|
||||
className="w-11 h-11 flex items-center justify-center bg-red-50 text-[#D40000] rounded-[10px] hover:bg-red-100 transition-colors"
|
||||
>
|
||||
<Trash2 size={16} strokeWidth={1.5} color="#D40000" />
|
||||
<TrashIcon size={16} strokeWidth={1.5} color="#D40000" />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
@@ -630,7 +630,7 @@ export default function AddPolicyEngine() {
|
||||
<CustomButton
|
||||
variant="secondary"
|
||||
className="!w-full !justify-center !bg-[#EAFAF5] hover:!bg-[#d9ece4] !px-4 !gap-2.5 !h-[49px] !rounded-[12px] whitespace-nowrap"
|
||||
leftIcon={<Plus size={16} color="#14704E" />}
|
||||
leftIcon={<PlusIcon size={16} color="#14704E" />}
|
||||
onClick={() => handleAddAction(rule.id)}
|
||||
>
|
||||
<span className="font-bold text-[14px] leading-none text-center bg-gradient-to-b from-[#1B9869] to-[#14704E] bg-clip-text text-transparent">
|
||||
@@ -645,7 +645,7 @@ export default function AddPolicyEngine() {
|
||||
onClick={() => handleDeleteAction(rule.id, action.id)}
|
||||
className="w-11 h-11 flex items-center justify-center bg-red-50 text-[#D40000] rounded-[10px] hover:bg-red-100 transition-colors"
|
||||
>
|
||||
<Trash2 size={16} strokeWidth={1.5} color="#D40000" />
|
||||
<TrashIcon size={16} strokeWidth={1.5} color="#D40000" />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import { Plus, Trash2, Search, Check, X, Pencil, Copy } from 'lucide-react';
|
||||
import { PlusIcon, TrashIcon, MagnifyingGlassIcon, XIcon, PencilSimpleIcon, CopyIcon, ChecksIcon } from '@phosphor-icons/react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import {
|
||||
CustomTable,
|
||||
@@ -183,7 +183,7 @@ export default function PolicyEngineList() {
|
||||
<CustomActionMenu>
|
||||
{row.status !== 'Active' && (
|
||||
<CustomActionItem
|
||||
icon={<Check size={15} />}
|
||||
icon={<ChecksIcon size={15} />}
|
||||
variant="success"
|
||||
onClick={() => setDeactivateTarget(row)}
|
||||
>
|
||||
@@ -192,26 +192,26 @@ export default function PolicyEngineList() {
|
||||
)}
|
||||
{row.status === 'Active' && (
|
||||
<CustomActionItem
|
||||
icon={<X size={15} />}
|
||||
icon={<XIcon size={15} />}
|
||||
onClick={() => setDeactivateTarget(row)}
|
||||
>
|
||||
Deactivate
|
||||
</CustomActionItem>
|
||||
)}
|
||||
<CustomActionItem
|
||||
icon={<Copy size={15} />}
|
||||
icon={<CopyIcon size={15} />}
|
||||
onClick={() => console.log('Duplicate:', row.id)}
|
||||
>
|
||||
Duplicate
|
||||
</CustomActionItem>
|
||||
<CustomActionItem
|
||||
icon={<Pencil size={15} />}
|
||||
icon={<PencilSimpleIcon size={15} />}
|
||||
onClick={() => console.log('Edit:', row.id)}
|
||||
>
|
||||
Edit
|
||||
</CustomActionItem>
|
||||
<CustomActionItem
|
||||
icon={<Trash2 size={15} />}
|
||||
icon={<TrashIcon size={15} />}
|
||||
variant="danger"
|
||||
onClick={() => setDeleteTarget(row)}
|
||||
>
|
||||
@@ -255,7 +255,7 @@ export default function PolicyEngineList() {
|
||||
placeholder="Search framework registry..."
|
||||
value={search}
|
||||
onChange={e => handleSearchChange(e.target.value)}
|
||||
leftIcon={<Search size={16} />}
|
||||
leftIcon={<MagnifyingGlassIcon size={16} />}
|
||||
className="!bg-[#F3F6F5] !rounded-[10px] !h-[38px] !border !border-[#E5E7EB]"
|
||||
containerClassName="!gap-0"
|
||||
/>
|
||||
@@ -266,7 +266,7 @@ export default function PolicyEngineList() {
|
||||
<CustomButton
|
||||
variant="primary"
|
||||
size="md"
|
||||
leftIcon={<Plus size={16} />}
|
||||
leftIcon={<PlusIcon size={16} />}
|
||||
className="!rounded-[10px] !gap-[10px] !h-[40px] !bg-[#1E7D5C] hover:!bg-[#17664B]"
|
||||
onClick={() => navigate('/policy-engine/add')}
|
||||
>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from "react";
|
||||
import { CircleCheck } from "lucide-react";
|
||||
import { CheckCircleIcon } from "@phosphor-icons/react";
|
||||
|
||||
interface CustomAccordionSectionProps {
|
||||
icon: React.ReactNode;
|
||||
@@ -27,7 +27,7 @@ const CustomAccordionSection: React.FC<CustomAccordionSectionProps> = ({
|
||||
>
|
||||
{icon}
|
||||
<span className="text-[11px] font-bold text-gray-700 uppercase tracking-wider flex-1">{title}</span>
|
||||
{!isOpen && hasData && <CircleCheck size={18} className="text-[#1B9869]" strokeWidth={2} />}
|
||||
{!isOpen && hasData && <CheckCircleIcon size={18} className="text-[#1B9869]" weight="fill" />}
|
||||
</button>
|
||||
{isOpen && <div className="px-4 pb-4 pt-3">{children}</div>}
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useCallback, useEffect, useRef, useState, useLayoutEffect } from "react";
|
||||
import { createPortal } from "react-dom";
|
||||
import { MoreVertical } from "lucide-react";
|
||||
import { DotsThreeVerticalIcon } from "@phosphor-icons/react";
|
||||
|
||||
interface CustomActionMenuProps {
|
||||
children: React.ReactNode;
|
||||
@@ -86,7 +86,7 @@ export const CustomActionMenu: React.FC<CustomActionMenuProps> = ({
|
||||
className={`flex h-8 w-8 items-center justify-center rounded-full transition-colors focus:outline-none ${isOpen ? 'bg-gray-100 text-black' : 'text-black hover:bg-gray-100'}`}
|
||||
aria-label="Actions"
|
||||
>
|
||||
<MoreVertical size={18} />
|
||||
<DotsThreeVerticalIcon size={18} />
|
||||
</button>
|
||||
|
||||
{isOpen &&
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { type FC, useEffect } from "react";
|
||||
import { AlertTriangle, CircleCheck, Info, XCircle, X } from 'lucide-react';
|
||||
import { WarningIcon, CheckCircleIcon, InfoIcon, XCircleIcon, XIcon } from '@phosphor-icons/react';
|
||||
|
||||
type AlertType = 'error' | 'success' | 'warning' | 'info';
|
||||
|
||||
@@ -13,19 +13,19 @@ interface AlertBannerProps {
|
||||
|
||||
const alertConfig = {
|
||||
error: {
|
||||
icon: <XCircle className="h-5 w-5" />,
|
||||
icon: <XCircleIcon className="h-5 w-5" />,
|
||||
containerClasses: 'bg-red-50 border-red-500 text-red-800',
|
||||
},
|
||||
success: {
|
||||
icon: <CircleCheck className="h-5 w-5" />,
|
||||
icon: <CheckCircleIcon className="h-5 w-5" />,
|
||||
containerClasses: 'bg-green-50 border-green-500 text-green-800',
|
||||
},
|
||||
warning: {
|
||||
icon: <AlertTriangle className="h-5 w-5" />,
|
||||
icon: <WarningIcon className="h-5 w-5" />,
|
||||
containerClasses: 'bg-yellow-50 border-yellow-500 text-yellow-800',
|
||||
},
|
||||
info: {
|
||||
icon: <Info className="h-5 w-5" />,
|
||||
icon: <InfoIcon className="h-5 w-5" />,
|
||||
containerClasses: 'bg-blue-50 border-blue-500 text-blue-800',
|
||||
},
|
||||
};
|
||||
@@ -75,7 +75,7 @@ const AlertBanner: FC<AlertBannerProps> = ({
|
||||
className="ml-4 p-1 rounded-full hover:bg-black/5 transition-colors focus:outline-none"
|
||||
aria-label="Close alert"
|
||||
>
|
||||
<X className="h-4 w-4" />
|
||||
<XIcon className="h-4 w-4" />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { Users, Briefcase, Building2 } from "lucide-react";
|
||||
import { UsersIcon, BriefcaseIcon, BuildingsIcon } from "@phosphor-icons/react";
|
||||
|
||||
const CustomAppLoader = () => {
|
||||
const [currentIndex, setCurrentIndex] = useState(0);
|
||||
|
||||
// HRM related icons
|
||||
const icons = [
|
||||
{ component: Users, key: "users" },
|
||||
{ component: Briefcase, key: "briefcase" },
|
||||
{ component: Building2, key: "building" },
|
||||
{ component: UsersIcon, key: "users" },
|
||||
{ component: BriefcaseIcon, key: "briefcase" },
|
||||
{ component: BuildingsIcon, key: "building" },
|
||||
];
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from "react";
|
||||
import { Link, useNavigate } from "react-router-dom";
|
||||
import { MoveLeft } from "lucide-react";
|
||||
import { ArrowLeftIcon } from "@phosphor-icons/react";
|
||||
|
||||
interface CustomBackButtonProps {
|
||||
to?: string;
|
||||
@@ -29,7 +29,7 @@ const CustomBackButton: React.FC<CustomBackButtonProps> = ({
|
||||
className={`group relative inline-flex items-center gap-2 text-gray-500 hover:text-gray-900 transition-colors cursor-pointer ${className}`}
|
||||
>
|
||||
<div className="flex h-8 w-8 items-center justify-center rounded-full bg-gray-100 hover:bg-gray-200 transition-colors">
|
||||
<MoveLeft className="h-4 w-4" />
|
||||
<ArrowLeftIcon className="h-4 w-4" />
|
||||
</div>
|
||||
{label && <span className="text-sm font-medium">{label}</span>}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { forwardRef } from "react";
|
||||
import { Check } from "lucide-react";
|
||||
import { CheckIcon } from "@phosphor-icons/react";
|
||||
|
||||
interface CustomCheckBoxProps
|
||||
extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "type"> {
|
||||
@@ -37,7 +37,7 @@ const CustomCheckBox = forwardRef<HTMLInputElement, CustomCheckBoxProps>(
|
||||
peer-disabled:bg-gray-100 peer-disabled:border-gray-200
|
||||
`}
|
||||
>
|
||||
<Check
|
||||
<CheckIcon
|
||||
size={14}
|
||||
className="text-white opacity-0 transition-opacity duration-200"
|
||||
strokeWidth={3}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from "react";
|
||||
import CustomModal from "./CustomModal";
|
||||
import CustomButton from "./CustomButton";
|
||||
import { AlertTriangle, CheckCircle } from "lucide-react";
|
||||
import { WarningIcon, CheckCircleIcon } from "@phosphor-icons/react";
|
||||
|
||||
interface ConfirmationModalProps {
|
||||
isOpen: boolean;
|
||||
@@ -40,7 +40,7 @@ const ConfirmationModal: React.FC<ConfirmationModalProps> = ({
|
||||
variant === 'success' ? 'bg-emerald-50 text-emerald-600' :
|
||||
'bg-blue-50 text-blue-600'
|
||||
}`}>
|
||||
{variant === 'success' ? <CheckCircle size={32} /> : <AlertTriangle size={32} />}
|
||||
{variant === 'success' ? <CheckCircleIcon size={32} /> : <WarningIcon size={32} />}
|
||||
</div>
|
||||
|
||||
<p className="text-gray-500 mb-6 font-medium">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { forwardRef } from "react";
|
||||
import { Calendar } from "lucide-react";
|
||||
import { CalendarBlankIcon } from "@phosphor-icons/react";
|
||||
|
||||
interface CustomDatePickerProps
|
||||
extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "type"> {
|
||||
@@ -42,7 +42,7 @@ const CustomDatePicker = forwardRef<HTMLInputElement, CustomDatePickerProps>(
|
||||
{...props}
|
||||
/>
|
||||
<span className="absolute left-3 top-1/2 -translate-y-1/2 text-slate-400 pointer-events-none">
|
||||
<Calendar size={18} />
|
||||
<CalendarBlankIcon size={18} />
|
||||
</span>
|
||||
</div>
|
||||
{error && <p className="text-xs text-red-500 mt-0.5">{error}</p>}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { forwardRef } from "react";
|
||||
import { CalendarClock } from "lucide-react";
|
||||
import { CalendarDotsIcon } from "@phosphor-icons/react";
|
||||
|
||||
interface CustomDateTimePickerProps
|
||||
extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "type"> {
|
||||
@@ -44,7 +44,7 @@ const CustomDateTimePicker = forwardRef<
|
||||
{...props}
|
||||
/>
|
||||
<span className="absolute left-3 top-1/2 -translate-y-1/2 text-slate-400 pointer-events-none">
|
||||
<CalendarClock size={18} />
|
||||
<CalendarDotsIcon size={18} />
|
||||
</span>
|
||||
</div>
|
||||
{error && <p className="text-xs text-red-500 mt-0.5">{error}</p>}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useState, useRef, useEffect } from "react";
|
||||
import { ChevronDown, Check } from "lucide-react";
|
||||
import { CaretDownIcon, CheckIcon } from "@phosphor-icons/react";
|
||||
import DropdownPortal from "./DropdownPortal";
|
||||
|
||||
interface Option {
|
||||
@@ -118,7 +118,7 @@ const CustomDropdown = React.forwardRef<HTMLDivElement, CustomDropdownProps>(
|
||||
</div>
|
||||
|
||||
<span className="absolute right-3 top-1/2 -translate-y-1/2 text-gray-500 pointer-events-none flex items-center">
|
||||
<ChevronDown
|
||||
<CaretDownIcon
|
||||
size={16}
|
||||
className={`transition-transform duration-200 ${isOpen ? "rotate-180" : ""}`}
|
||||
/>
|
||||
@@ -157,7 +157,7 @@ const CustomDropdown = React.forwardRef<HTMLDivElement, CustomDropdownProps>(
|
||||
}
|
||||
`}
|
||||
>
|
||||
{isSelected && <Check size={16} className="text-primary shrink-0" strokeWidth={2.5} />}
|
||||
{isSelected && <CheckIcon size={16} className="text-primary shrink-0" strokeWidth={2.5} />}
|
||||
<span
|
||||
className={
|
||||
isSelected
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useRef, useState, useEffect } from "react";
|
||||
import { Upload, X, File } from "lucide-react";
|
||||
import { UploadSimpleIcon, XIcon, FileIcon } from "@phosphor-icons/react";
|
||||
|
||||
interface CustomFileUploaderProps {
|
||||
label?: string;
|
||||
@@ -141,7 +141,7 @@ const CustomFileUploader: React.FC<CustomFileUploaderProps> = ({
|
||||
/>
|
||||
|
||||
<div className="flex flex-col items-center gap-2 text-gray-500">
|
||||
<Upload size={24} />
|
||||
<UploadSimpleIcon size={24} />
|
||||
<span className="text-sm font-medium">
|
||||
{isDragging ? "Drop files here" : "Click or drag to upload"}
|
||||
</span>
|
||||
@@ -185,7 +185,7 @@ const CustomFileUploader: React.FC<CustomFileUploaderProps> = ({
|
||||
}}
|
||||
className="p-1 text-gray-400 hover:text-red-500 transition-colors rounded-full hover:bg-gray-100"
|
||||
>
|
||||
<X size={18} />
|
||||
<XIcon size={18} />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
@@ -206,7 +206,7 @@ const CustomFileUploader: React.FC<CustomFileUploaderProps> = ({
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
) : (
|
||||
<File size={20} className="text-gray-500" />
|
||||
<FileIcon size={20} className="text-gray-500" />
|
||||
)}
|
||||
</div>
|
||||
<div className="flex flex-col overflow-hidden">
|
||||
@@ -223,7 +223,7 @@ const CustomFileUploader: React.FC<CustomFileUploaderProps> = ({
|
||||
onClick={(e) => removeFile(e, index)}
|
||||
className="p-1 text-gray-400 hover:text-[#0B3B6A] transition-colors rounded-full hover:bg-gray-100"
|
||||
>
|
||||
<X size={18} />
|
||||
<XIcon size={18} />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { X } from "lucide-react";
|
||||
import { XIcon } from "@phosphor-icons/react";
|
||||
|
||||
interface FullModalProps {
|
||||
isOpen: boolean;
|
||||
@@ -61,7 +61,7 @@ const FullModal: React.FC<FullModalProps> = ({
|
||||
onClick={onClose}
|
||||
className="absolute top-4 right-4 z-50 p-2 bg-black/10 hover:bg-black/20 rounded-full transition-colors md:top-6 md:right-6"
|
||||
>
|
||||
<X size={24} className="text-gray-700" />
|
||||
<XIcon size={24} className="text-gray-700" />
|
||||
</button>
|
||||
)}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useState, forwardRef } from "react";
|
||||
import { Phone, Eye, EyeOff } from "lucide-react";
|
||||
import { PhoneIcon, EyeIcon, EyeSlashIcon } from "@phosphor-icons/react";
|
||||
|
||||
type InputType = "text" | "password" | "number" | "email" | "tel" | "date" | "month" | "datetime-local";
|
||||
|
||||
@@ -73,7 +73,7 @@ const CustomInput = forwardRef<HTMLInputElement, CustomInputProps>(
|
||||
>
|
||||
{isPhone && (
|
||||
<div className="flex items-center gap-2 border-r border-gray-300 bg-gray-50 px-3 text-sm font-semibold text-gray-900">
|
||||
<Phone size={16} className="text-gray-500" />
|
||||
<PhoneIcon size={16} className="text-gray-500" />
|
||||
{phonePrefix}
|
||||
</div>
|
||||
)}
|
||||
@@ -120,7 +120,7 @@ const CustomInput = forwardRef<HTMLInputElement, CustomInputProps>(
|
||||
onClick={() => setShowPassword(!showPassword)}
|
||||
className="absolute right-3 top-1/2 -translate-y-1/2 cursor-pointer text-slate-400 select-none hover:text-primary"
|
||||
>
|
||||
{showPassword ? <Eye size={20} /> : <EyeOff size={20} />}
|
||||
{showPassword ? <EyeIcon size={20} /> : <EyeSlashIcon size={20} />}
|
||||
</span>
|
||||
) : (
|
||||
!isPhone &&
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { createPortal } from "react-dom";
|
||||
import { XCircle } from "lucide-react";
|
||||
import { XCircleIcon } from "@phosphor-icons/react";
|
||||
import CustomButton from "./CustomButton";
|
||||
|
||||
type ModalSize = "sm" | "md" | "lg" | "xl" | "full";
|
||||
@@ -140,7 +140,7 @@ const CustomModal: React.FC<CustomModalProps> = ({
|
||||
className="absolute right-4 top-4 flex h-8 w-8 items-center justify-center rounded-full
|
||||
text-slate-400 transition hover:text-slate-600 hover:bg-slate-100"
|
||||
>
|
||||
<XCircle size={20} strokeWidth={2} />
|
||||
<XCircleIcon size={20} strokeWidth={2} />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useState, useRef, useEffect } from "react";
|
||||
import { ChevronDown, Check } from "lucide-react";
|
||||
import { CaretDownIcon, CheckIcon } from "@phosphor-icons/react";
|
||||
import DropdownPortal from "./DropdownPortal";
|
||||
|
||||
interface Option {
|
||||
@@ -127,7 +127,7 @@ const CustomMultiSelect = React.forwardRef<HTMLDivElement, CustomMultiSelectProp
|
||||
</div>
|
||||
|
||||
<span className="absolute right-3 top-1/2 -translate-y-1/2 text-gray-500 pointer-events-none flex items-center">
|
||||
<ChevronDown
|
||||
<CaretDownIcon
|
||||
size={16}
|
||||
className={`transition-transform duration-200 ${isOpen ? "rotate-180" : ""}`}
|
||||
/>
|
||||
@@ -166,7 +166,7 @@ const CustomMultiSelect = React.forwardRef<HTMLDivElement, CustomMultiSelectProp
|
||||
}
|
||||
`}
|
||||
>
|
||||
{isSelected && <Check size={16} className="text-[#1B9869] shrink-0" strokeWidth={2.5} />}
|
||||
{isSelected && <CheckIcon size={16} className="text-[#1B9869] shrink-0" strokeWidth={2.5} />}
|
||||
<span className={isSelected ? "ml-1" : "ml-6"}>{option.label}</span>
|
||||
</button>
|
||||
);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useState, useRef, useEffect } from "react";
|
||||
import { ChevronDown, X, Check } from "lucide-react";
|
||||
import { CaretDownIcon, XIcon, CheckIcon } from "@phosphor-icons/react";
|
||||
import DropdownPortal from "./DropdownPortal";
|
||||
|
||||
interface Option {
|
||||
@@ -205,7 +205,7 @@ const CustomSearchableDropdown = React.forwardRef<
|
||||
disabled={disabled}
|
||||
tabIndex={-1}
|
||||
>
|
||||
<ChevronDown
|
||||
<CaretDownIcon
|
||||
size={16}
|
||||
className={`transition-transform duration-200 ${isOpen ? "rotate-180" : ""}`}
|
||||
/>
|
||||
@@ -214,7 +214,7 @@ const CustomSearchableDropdown = React.forwardRef<
|
||||
|
||||
{searchTerm && !disabled && (
|
||||
<button type="button" onClick={handleClear} className="text-gray-500 hover:text-gray-900 p-0.5">
|
||||
<X size={16} />
|
||||
<XIcon size={16} />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
@@ -248,7 +248,7 @@ const CustomSearchableDropdown = React.forwardRef<
|
||||
}
|
||||
`}
|
||||
>
|
||||
{isSelected && <Check size={16} className="text-primary shrink-0" strokeWidth={2.5} />}
|
||||
{isSelected && <CheckIcon size={16} className="text-primary shrink-0" strokeWidth={2.5} />}
|
||||
<span
|
||||
className={
|
||||
isSelected
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { createPortal } from "react-dom";
|
||||
import { X } from "lucide-react";
|
||||
import { XIcon } from "@phosphor-icons/react";
|
||||
import CustomStatus from "./CustomStatus";
|
||||
import SuccessTick from "../../assets/icons/SuccessTick.png";
|
||||
|
||||
@@ -58,7 +58,7 @@ const CustomSuccessModal: React.FC<CustomSuccessModalProps> = ({
|
||||
onClick={onClose}
|
||||
className="absolute top-4 right-4 text-gray-500 hover:text-gray-700 focus:outline-none"
|
||||
>
|
||||
<X size={24} strokeWidth={2.5} className="text-[#152A3C]" />
|
||||
<XIcon size={24} weight="bold" className="text-[#152A3C]" />
|
||||
</button>
|
||||
|
||||
{/* Animated Icon Background */}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from "react";
|
||||
import { Search, ChevronLeft, ChevronRight, Filter, ArrowDownUp } from "lucide-react";
|
||||
import { MagnifyingGlassIcon, CaretLeftIcon, CaretRightIcon, FunnelSimpleIcon, ArrowsDownUpIcon } from "@phosphor-icons/react";
|
||||
import CustomInput from "./CustomInput";
|
||||
|
||||
export interface Column<T> {
|
||||
@@ -80,7 +80,7 @@ export function CustomTable<T>({
|
||||
placeholder={searchPlaceholder}
|
||||
value={searchValue}
|
||||
onChange={(e) => onSearchChange(e.target.value)}
|
||||
leftIcon={<Search size={18} />}
|
||||
leftIcon={<MagnifyingGlassIcon size={18} />}
|
||||
size="sm"
|
||||
containerClassName="!gap-0"
|
||||
/>
|
||||
@@ -106,8 +106,8 @@ export function CustomTable<T>({
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
{col.header}
|
||||
{col.sortable && <ArrowDownUp size={14} className="cursor-pointer hover:text-gray-900" />}
|
||||
{col.filterable && <Filter size={14} className="cursor-pointer hover:text-gray-900" />}
|
||||
{col.sortable && <ArrowsDownUpIcon size={14} className="cursor-pointer hover:text-gray-900" />}
|
||||
{col.filterable && <FunnelSimpleIcon size={14} className="cursor-pointer hover:text-gray-900" />}
|
||||
</div>
|
||||
</th>
|
||||
))}
|
||||
@@ -153,7 +153,7 @@ export function CustomTable<T>({
|
||||
disabled={currentPage === 1}
|
||||
className="w-8 h-8 flex items-center justify-center rounded-lg border border-[#9FACA1] bg-white text-[#9FACA1] hover:bg-gray-50 hover:text-gray-900 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
|
||||
>
|
||||
<ChevronLeft size={16} />
|
||||
<CaretLeftIcon size={16} />
|
||||
</button>
|
||||
|
||||
<div className="flex items-center gap-1">
|
||||
@@ -178,7 +178,7 @@ export function CustomTable<T>({
|
||||
disabled={currentPage === totalPages}
|
||||
className="w-8 h-8 flex items-center justify-center rounded-lg border border-[#9FACA1] bg-white text-[#9FACA1] hover:bg-gray-50 hover:text-gray-900 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
|
||||
>
|
||||
<ChevronRight size={16} />
|
||||
<CaretRightIcon size={16} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { forwardRef } from "react";
|
||||
import { Clock } from "lucide-react";
|
||||
import { ClockIcon } from "@phosphor-icons/react";
|
||||
|
||||
interface CustomTimePickerProps
|
||||
extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "type"> {
|
||||
@@ -42,7 +42,7 @@ const CustomTimePicker = forwardRef<HTMLInputElement, CustomTimePickerProps>(
|
||||
{...props}
|
||||
/>
|
||||
<span className="absolute left-3 top-1/2 -translate-y-1/2 text-slate-400 pointer-events-none">
|
||||
<Clock size={18} />
|
||||
<ClockIcon size={18} />
|
||||
</span>
|
||||
</div>
|
||||
{error && <p className="text-xs text-red-500 mt-0.5">{error}</p>}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Bell, Menu } from 'lucide-react';
|
||||
import { BellIcon, ListIcon } from '@phosphor-icons/react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
|
||||
const PAGE_META: Record<string, { title: string; subtitle: string }> = {
|
||||
@@ -22,7 +22,7 @@ export default function AppHeader({ onMenuClick }: AppHeaderProps) {
|
||||
onClick={onMenuClick}
|
||||
className="lg:hidden p-2 text-slate-500 hover:bg-slate-100 rounded-lg transition-colors"
|
||||
>
|
||||
<Menu size={24} strokeWidth={2} />
|
||||
<ListIcon size={24} weight="bold" />
|
||||
</button>
|
||||
<div className="flex flex-col justify-center">
|
||||
<h1 className="text-lg md:text-[18px] font-bold text-[#111827] tracking-tight">{meta.title}</h1>
|
||||
@@ -31,7 +31,7 @@ export default function AppHeader({ onMenuClick }: AppHeaderProps) {
|
||||
</div>
|
||||
<div className="flex items-center gap-2 md:gap-4">
|
||||
<button className="relative p-2 text-slate-500 hover:bg-slate-100 rounded-full transition-colors">
|
||||
<Bell size={20} strokeWidth={2} />
|
||||
<BellIcon size={20} weight="bold" />
|
||||
<span className="absolute top-2 right-2 w-2 h-2 bg-red-500 rounded-full border-[1.5px] border-white"></span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
+23
-23
@@ -1,27 +1,27 @@
|
||||
import { useState } from 'react';
|
||||
import { Link, useLocation } from 'react-router-dom';
|
||||
import {
|
||||
Settings2,
|
||||
RefreshCcw,
|
||||
Users,
|
||||
ShieldCheck,
|
||||
Settings,
|
||||
History,
|
||||
LogOut,
|
||||
HelpCircle,
|
||||
ChevronsLeft,
|
||||
ChevronsRight,
|
||||
LayoutGrid
|
||||
} from 'lucide-react';
|
||||
ShieldCheckIcon,
|
||||
GearIcon,
|
||||
ClockCounterClockwiseIcon,
|
||||
CaretDoubleRightIcon,
|
||||
SquaresFourIcon,
|
||||
FadersIcon,
|
||||
ArrowsClockwiseIcon,
|
||||
UsersFourIcon,
|
||||
CaretDoubleLeftIcon,
|
||||
SignOutIcon,
|
||||
QuestionIcon
|
||||
} from '@phosphor-icons/react';
|
||||
|
||||
const NAV_ITEMS = [
|
||||
{ label: 'Dashboard', path: '/', icon: LayoutGrid },
|
||||
{ label: 'Simulation Engine', path: '/simulation', icon: Settings2 },
|
||||
{ label: 'Recovery Incidents', path: '/recovery', icon: RefreshCcw },
|
||||
{ label: 'Cohort Management', path: '/cohorts', icon: Users },
|
||||
{ label: 'Policy Engine', path: '/policy-engine', icon: ShieldCheck },
|
||||
{ label: 'Configuration', path: '/config', icon: Settings },
|
||||
{ label: 'Audit Logs', path: '/audit', icon: History },
|
||||
{ label: 'Dashboard', path: '/', icon: SquaresFourIcon },
|
||||
{ label: 'Simulation Engine', path: '/simulation', icon: FadersIcon },
|
||||
{ label: 'Recovery Incidents', path: '/recovery', icon: ArrowsClockwiseIcon },
|
||||
{ label: 'Cohort Management', path: '/cohorts', icon: UsersFourIcon },
|
||||
{ label: 'Policy Engine', path: '/policy-engine', icon: ShieldCheckIcon },
|
||||
{ label: 'Configuration', path: '/config', icon: GearIcon },
|
||||
{ label: 'Audit Logs', path: '/audit', icon: ClockCounterClockwiseIcon },
|
||||
];
|
||||
|
||||
interface AppSidebarProps {
|
||||
@@ -60,13 +60,13 @@ export default function AppSidebar({ isOpen, onClose }: AppSidebarProps) {
|
||||
)}
|
||||
</div>
|
||||
<button onClick={onClose} className="text-slate-400 hover:text-slate-600 transition-colors lg:hidden">
|
||||
<ChevronsLeft size={20} strokeWidth={2} />
|
||||
<CaretDoubleLeftIcon size={20} weight="bold" />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setIsCollapsed(!isCollapsed)}
|
||||
className="text-slate-400 hover:text-slate-600 transition-colors hidden lg:block"
|
||||
>
|
||||
{isCollapsed ? <ChevronsRight size={20} strokeWidth={2} /> : <ChevronsLeft size={20} strokeWidth={2} />}
|
||||
{isCollapsed ? <CaretDoubleRightIcon size={20} weight="bold" /> : <CaretDoubleLeftIcon size={20} weight="bold" />}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -113,11 +113,11 @@ export default function AppSidebar({ isOpen, onClose }: AppSidebarProps) {
|
||||
|
||||
<div className={`relative z-10 flex flex-col ${isCollapsed ? 'gap-2 w-full' : 'gap-0.5'}`}>
|
||||
<button title={isCollapsed ? "Sign Out" : undefined} className={`flex items-center ${isCollapsed ? 'justify-center px-0 h-10 w-full' : 'gap-3 px-3 py-2'} text-[13px] font-semibold text-[#E02424] hover:bg-red-50/50 rounded-[10px] transition-colors`}>
|
||||
<LogOut size={17} className="text-[#E02424] shrink-0" strokeWidth={2} />
|
||||
<SignOutIcon size={17} className="text-[#E02424] shrink-0" weight="bold" />
|
||||
{!isCollapsed && <span className="whitespace-nowrap">Sign Out</span>}
|
||||
</button>
|
||||
<button title={isCollapsed ? "Help Center" : undefined} className={`flex items-center ${isCollapsed ? 'justify-center px-0 h-10 w-full' : 'gap-3 px-3 py-2'} text-[13px] font-medium text-slate-700 hover:bg-white/40 rounded-[10px] transition-colors`}>
|
||||
<HelpCircle size={17} className="text-slate-700 shrink-0" strokeWidth={1.5} />
|
||||
<QuestionIcon size={17} className="text-slate-700 shrink-0" weight="regular" />
|
||||
{!isCollapsed && <span className="whitespace-nowrap">Help center</span>}
|
||||
</button>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user