All files / src/components/admin/pros CreateProModal.tsx

96.29% Statements 26/27
75% Branches 6/8
100% Functions 4/4
100% Lines 25/25

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110                            248x 248x 248x 248x   248x 8x 8x 8x 8x 8x       4x 4x 4x 4x     3x 3x   7x       248x 5x 5x 5x     248x   248x   101x                                                                         58x                                          
import { useState } from "react";
import { useNavigate } from "@tanstack/react-router";
import { X } from "lucide-react";
import { Button } from "../../ui/button";
import { Input } from "../../ui/input";
import { adminApi } from "../../../lib/api";
import { useDialogAccessibility } from "../../../hooks";
 
interface CreateProModalProps {
	isOpen: boolean;
	onClose: () => void;
}
 
export function CreateProModal({ isOpen, onClose }: CreateProModalProps) {
	const navigate = useNavigate();
	const [businessName, setBusinessName] = useState("");
	const [isCreating, setIsCreating] = useState(false);
	const [error, setError] = useState<string | null>(null);
 
	const handleCreatePro = async () => {
		Iif (!businessName.trim()) return;
		setIsCreating(true);
		setError(null);
		try {
			const result = await adminApi.createPro({
				businessName,
				status: "draft",
			});
			Eif (result.data) {
				onClose();
				setBusinessName("");
				navigate({ to: `/admin/pros/${result.data.id}` });
			}
		} catch (err) {
			console.error("Failed to create pro:", err);
			setError("Failed to create pro");
		} finally {
			setIsCreating(false);
		}
	};
 
	const handleClose = () => {
		onClose();
		setError(null);
		setBusinessName("");
	};
 
	const { dialogRef, handleFocusTrap } = useDialogAccessibility(handleClose);
 
	if (!isOpen) return null;
 
	return (
		<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50" tabIndex={-1}>
			<div
				ref={dialogRef}
				role="dialog"
				aria-modal="true"
				aria-labelledby="create-pro-dialog-title"
				onKeyDown={handleFocusTrap}
				className="bg-background-elevated rounded-lg shadow-xl w-full max-w-md mx-4"
			>
				<div className="flex items-center justify-between p-4 border-b">
					<h3 id="create-pro-dialog-title" className="text-lg font-semibold">Create New Pro</h3>
					<button
						type="button"
						onClick={handleClose}
						aria-label="Close"
						className="p-1 hover:bg-background-subtle rounded"
					>
						<X className="h-5 w-5" />
					</button>
				</div>
				<div className="p-4 space-y-4">
					{error && (
						<div className="bg-notification-error-bg text-notification-error-text px-3 py-2 rounded text-sm">
							{error}
						</div>
					)}
					<div>
						<label
							htmlFor="new-pro-business-name"
							className="block text-sm font-medium text-foreground-default mb-1"
						>
							Business Name *
						</label>
						<Input
							id="new-pro-business-name"
							value={businessName}
							onChange={(e) => setBusinessName(e.target.value)}
							placeholder="Enter business name"
						/>
					</div>
				</div>
				<div className="flex justify-end gap-2 p-4 border-t">
					<Button variant="outline" onClick={handleClose}>
						Cancel
					</Button>
					<Button
						onClick={handleCreatePro}
						isLoading={isCreating}
						disabled={!businessName.trim()}
					>
						Create Pro
					</Button>
				</div>
			</div>
		</div>
	);
}