feat(platform): add Provisioning Success Modal with 1-click Copy Credentials button for tenant onboarding

This commit is contained in:
Inamul-hasan-tec
2026-08-08 15:19:01 +05:30
parent 9fc4b34e60
commit 1c0595d8b2
@@ -1,5 +1,5 @@
import { useEffect, useState } from "react";
import { Plus, Building2, Search, Play, StopCircle, CheckCircle, XCircle } from "lucide-react";
import { Plus, Building2, Search, Play, StopCircle, CheckCircle, XCircle, Copy, Check } from "lucide-react";
import { useNavigate } from "react-router-dom";
import { PageWrapper } from "../../../components/layouts/PageWrapper";
import { Breadcrumb } from "../../../components/layouts/Breadcrumb";
@@ -37,6 +37,9 @@ export default function PlatformTenantsPage() {
loadData();
}, []);
const [provisionedSuccessData, setProvisionedSuccessData] = useState<any | null>(null);
const [copied, setCopied] = useState(false);
const formik = useFormik({
initialValues: {
tenant_name: "",
@@ -54,9 +57,14 @@ export default function PlatformTenantsPage() {
}),
onSubmit: async (values, { setSubmitting, resetForm }) => {
try {
await provisionTenant(values);
const result = await provisionTenant(values);
resetForm();
setIsProvisionModalOpen(false);
setProvisionedSuccessData({
tenant: result.tenant || result.data?.tenant,
admin: result.admin || result.data?.admin,
rawPassword: values.admin_password
});
fetchPlatformTenants();
} catch (err) {
// Error handled in hook
@@ -308,6 +316,62 @@ export default function PlatformTenantsPage() {
</div>
</div>
)}
{/* Provisioning Success Modal with Copy Credentials */}
{provisionedSuccessData && (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-sm p-4 animate-in fade-in duration-200">
<div className="w-full max-w-md bg-surface border border-primary/20 rounded-2xl p-6 shadow-2xl space-y-5">
<div className="flex items-center gap-3">
<div className="w-12 h-12 rounded-xl bg-success/10 text-success flex items-center justify-center">
<CheckCircle className="w-6 h-6" />
</div>
<div>
<h3 className="text-lg font-bold text-foreground">Tenant Provisioned!</h3>
<p className="text-xs text-muted-foreground">Share these setup credentials with your client</p>
</div>
</div>
<div className="bg-primary/5 border border-primary/10 rounded-xl p-4 space-y-3 font-mono text-xs text-foreground">
<div className="flex justify-between border-b border-primary/10 pb-2">
<span className="text-muted-foreground font-sans">Organization:</span>
<span className="font-semibold text-primary">{provisionedSuccessData.tenant?.tenant_name}</span>
</div>
<div className="flex justify-between border-b border-primary/10 pb-2">
<span className="text-muted-foreground font-sans">Tenant Code:</span>
<span className="font-semibold">{provisionedSuccessData.tenant?.tenant_code}</span>
</div>
<div className="flex justify-between border-b border-primary/10 pb-2">
<span className="text-muted-foreground font-sans">Admin Email:</span>
<span className="font-semibold">{provisionedSuccessData.admin?.email || provisionedSuccessData.tenant?.contact_email}</span>
</div>
<div className="flex justify-between">
<span className="text-muted-foreground font-sans">Admin Password:</span>
<span className="font-semibold text-danger">{provisionedSuccessData.rawPassword || '••••••••'}</span>
</div>
</div>
<div className="flex items-center gap-3 pt-2">
<Button
variant="primary"
className="w-full flex items-center justify-center gap-2"
onClick={() => {
const textToCopy = `Organization: ${provisionedSuccessData.tenant?.tenant_name}\nTenant Code: ${provisionedSuccessData.tenant?.tenant_code}\nAdmin Email: ${provisionedSuccessData.admin?.email || provisionedSuccessData.tenant?.contact_email}\nPassword: ${provisionedSuccessData.rawPassword || 'Admin@123'}\nLogin URL: http://localhost:5173/login`;
navigator.clipboard.writeText(textToCopy);
setCopied(true);
notify.success("Provisioning credentials copied to clipboard!");
setTimeout(() => setCopied(false), 2000);
}}
>
{copied ? <Check className="w-4 h-4" /> : <Copy className="w-4 h-4" />}
{copied ? "Copied to Clipboard!" : "Copy Client Credentials"}
</Button>
<Button variant="outline" onClick={() => setProvisionedSuccessData(null)}>
Done
</Button>
</div>
</div>
</div>
)}
</PageWrapper>
);
}