feat: implement cohort creation and editing modal with multi-step wizard and success feedback

This commit is contained in:
azeeee05
2026-07-09 10:40:10 +05:30
parent fc1cfc447c
commit 218670d336
3 changed files with 72 additions and 38 deletions
+18 -2
View File
@@ -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

+53 -35
View File
@@ -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
);
};