feat: implement cohort creation and editing modal with multi-step wizard and success feedback
This commit is contained in:
@@ -10,6 +10,7 @@ import {
|
||||
CustomRadio,
|
||||
CustomCheckBox,
|
||||
} from '../../../components/custom';
|
||||
import CustomSuccessModal from '../../../components/custom/CustomSuccessModal';
|
||||
import { createCohart, updateCohart } from '../CohartManageApi';
|
||||
import {
|
||||
getCabinClasses,
|
||||
@@ -135,6 +136,7 @@ export default function AddCohart({ isOpen, onClose, onSuccess, editData }: AddC
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [openSection, setOpenSection] = useState('passenger');
|
||||
const [showSuccessModal, setShowSuccessModal] = useState(false);
|
||||
|
||||
// Step 1
|
||||
const [stepOne, setStepOne] = useState<StepOneData>(EMPTY_STEP_ONE);
|
||||
@@ -240,8 +242,7 @@ export default function AddCohart({ isOpen, onClose, onSuccess, editData }: AddC
|
||||
await createCohart(payload);
|
||||
}
|
||||
|
||||
handleClose();
|
||||
onSuccess();
|
||||
setShowSuccessModal(true);
|
||||
} catch {
|
||||
setError(`Failed to ${isEditMode ? 'update' : 'create'} cohort. Please try again.`);
|
||||
} finally {
|
||||
@@ -315,6 +316,7 @@ export default function AddCohart({ isOpen, onClose, onSuccess, editData }: AddC
|
||||
// ─── Render ────────────────────────────────────────────────────────────────
|
||||
|
||||
return (
|
||||
<>
|
||||
<CustomModal
|
||||
isOpen={isOpen}
|
||||
onClose={handleClose}
|
||||
@@ -532,5 +534,19 @@ export default function AddCohart({ isOpen, onClose, onSuccess, editData }: AddC
|
||||
)}
|
||||
</div>
|
||||
</CustomModal>
|
||||
|
||||
<CustomSuccessModal
|
||||
isOpen={showSuccessModal}
|
||||
onClose={() => {
|
||||
setShowSuccessModal(false);
|
||||
handleClose();
|
||||
onSuccess();
|
||||
}}
|
||||
title={isEditMode ? "Cohort Updated Successfully." : "Cohort Created Successfully."}
|
||||
cohortName={stepOne.name}
|
||||
cohortStatus={stepOne.status}
|
||||
cohortDescription={stepOne.description}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
@@ -1,19 +1,25 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { createPortal } from "react-dom";
|
||||
import { X } from "lucide-react";
|
||||
import CustomStatus from "./CustomStatus";
|
||||
import SuccessTick from "../../assets/icons/SuccessTick.png";
|
||||
|
||||
interface CustomSuccessModalProps {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
title?: string;
|
||||
description?: string;
|
||||
buttonText?: string;
|
||||
cohortName?: string;
|
||||
cohortStatus?: string;
|
||||
cohortDescription?: string;
|
||||
}
|
||||
|
||||
const CustomSuccessModal: React.FC<CustomSuccessModalProps> = ({
|
||||
isOpen,
|
||||
onClose,
|
||||
title = "Success!",
|
||||
description = "Your action has been completed successfully.",
|
||||
buttonText = "Continue",
|
||||
title = "Cohort Created Successfully.",
|
||||
cohortName,
|
||||
cohortStatus,
|
||||
cohortDescription,
|
||||
}) => {
|
||||
useEffect(() => {
|
||||
const handleEsc = (e: KeyboardEvent) => {
|
||||
@@ -33,7 +39,7 @@ const CustomSuccessModal: React.FC<CustomSuccessModalProps> = ({
|
||||
|
||||
if (!isOpen) return null;
|
||||
|
||||
return (
|
||||
return createPortal(
|
||||
<div className="fixed inset-0 z-[10000] flex items-center justify-center">
|
||||
{/* Overlay */}
|
||||
<div
|
||||
@@ -43,47 +49,59 @@ const CustomSuccessModal: React.FC<CustomSuccessModalProps> = ({
|
||||
|
||||
{/* Modal Content */}
|
||||
<div
|
||||
className="relative z-10 flex w-full max-w-sm flex-col items-center justify-center overflow-hidden rounded-3xl bg-white p-8 text-center shadow-2xl animate-in zoom-in-95 fade-in duration-300 sm:max-w-md"
|
||||
className="relative z-10 flex w-full max-w-lg flex-col items-center justify-center overflow-hidden rounded-xl bg-white p-8 text-center shadow-2xl animate-in zoom-in-95 fade-in duration-300"
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
>
|
||||
{/* Animated Icon Background */}
|
||||
<div className="mb-6 flex h-24 w-24 items-center justify-center rounded-full bg-primary/10">
|
||||
<div className="flex h-16 w-16 items-center justify-center rounded-full bg-primary/20 animate-pulse">
|
||||
<svg
|
||||
className="h-8 w-8 text-primary"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{/* Close Button */}
|
||||
<button
|
||||
onClick={onClose}
|
||||
className="absolute top-4 right-4 text-gray-500 hover:text-gray-700 focus:outline-none"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={3}
|
||||
d="M5 13l4 4L19 7"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<X size={24} strokeWidth={2.5} className="text-[#152A3C]" />
|
||||
</button>
|
||||
|
||||
{/* Animated Icon Background */}
|
||||
<div className="mb-6 mt-4 flex items-center justify-center">
|
||||
<img src={SuccessTick} alt="Success" className="h-16 w-16" />
|
||||
</div>
|
||||
|
||||
{/* Content */}
|
||||
<h3 className="mb-2 text-2xl font-bold text-gray-900">
|
||||
<h3 className="mb-6 text-[28px] font-extrabold text-[#152A3C]">
|
||||
{title}
|
||||
</h3>
|
||||
<p className="mb-8 text-center text-gray-500 leading-relaxed">
|
||||
{description}
|
||||
</p>
|
||||
|
||||
{/* Action Button */}
|
||||
<button
|
||||
onClick={onClose}
|
||||
className="w-full rounded-xl bg-primary py-3.5 px-4 text-base font-semibold text-white shadow-lg transition-all hover:bg-primary-dark hover:shadow-xl hover:-translate-y-0.5 active:translate-y-0 focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2"
|
||||
>
|
||||
{buttonText}
|
||||
</button>
|
||||
{cohortName && (
|
||||
<div className="w-full rounded-[12px] bg-[#F4F8FA] p-5 text-left border border-blue-50/50">
|
||||
<div className="flex justify-between items-start mb-4">
|
||||
<div>
|
||||
<p className="text-[10px] font-bold tracking-wider text-[#1B9869] uppercase mb-1">
|
||||
COHORT NAME
|
||||
</p>
|
||||
<p className="text-base font-bold text-[#152A3C]">
|
||||
{cohortName}
|
||||
</p>
|
||||
</div>
|
||||
{cohortStatus && (
|
||||
<CustomStatus status={cohortStatus as any} />
|
||||
)}
|
||||
</div>
|
||||
|
||||
{cohortDescription && (
|
||||
<div>
|
||||
<p className="text-[10px] font-bold tracking-wider text-[#1B9869] uppercase mb-1">
|
||||
DESCRIPTION
|
||||
</p>
|
||||
<p className="text-[13px] font-medium text-[#152A3C]">
|
||||
{cohortDescription}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>,
|
||||
document.body
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user