merged code with dev

This commit is contained in:
azeeee05
2026-07-21 11:21:38 +05:30
28 changed files with 144 additions and 129 deletions
+14
View File
@@ -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",
+1
View File
@@ -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)}
>
+9 -9
View File
@@ -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>
+2 -2
View File
@@ -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 &&
+6 -6
View File
@@ -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>
+4 -4
View File
@@ -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(() => {
+2 -2
View File
@@ -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>}
+2 -2
View File
@@ -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">
+2 -2
View File
@@ -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>}
+3 -3
View File
@@ -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
+5 -5
View File
@@ -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>
+2 -2
View File
@@ -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>
)}
+3 -3
View File
@@ -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 &&
+2 -2
View File
@@ -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>
+3 -3
View File
@@ -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
+2 -2
View File
@@ -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 */}
+6 -6
View File
@@ -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>
+2 -2
View File
@@ -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>}
+3 -3
View File
@@ -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
View File
@@ -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>