Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 75 additions & 52 deletions frontend/src/components/residents/ResidentDialogs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ import { FormModal, TonedPanel } from '@/components/shared';
import { useTypeToConfirm } from '@/components/shared/useTypeToConfirm';
import { Copy, Check } from 'lucide-react';

function useConfirmToken(resident: User, open: boolean) {
const hasDocId = Boolean(resident.doc_id);
const confirmToken = hasDocId ? resident.doc_id! : resident.username;
const confirmLabel = hasDocId ? 'Resident ID' : 'username';
const confirm = useTypeToConfirm({ open, expected: confirmToken });
return { confirmToken, confirmLabel, confirm };
}

// ---------------------------------------------------------------------------
// EditResidentDialog
// ---------------------------------------------------------------------------
Expand Down Expand Up @@ -90,56 +98,65 @@ export function EditResidentDialog({
description="Update resident information"
titleClassName="text-foreground"
>
<div className="space-y-4 py-4">
<div className="grid grid-cols-2 gap-4">
<form
onSubmit={(e) => {
void form.handleSubmit((d) => void handleSave(d))(e);
}}
>
Comment thread
coderabbitai[bot] marked this conversation as resolved.
<div className="space-y-4 py-4">
<div className="grid grid-cols-2 gap-4">
<div>
<Label htmlFor="edit-first">First Name</Label>
<Input
id="edit-first"
{...form.register('name_first', {
required: true
})}
className="mt-2"
/>
</div>
<div>
<Label htmlFor="edit-last">Last Name</Label>
<Input
id="edit-last"
{...form.register('name_last', {
required: true
})}
className="mt-2"
/>
</div>
</div>
<div>
<Label htmlFor="edit-first">First Name</Label>
<Label htmlFor="edit-username">Username</Label>
<Input
id="edit-first"
{...form.register('name_first', { required: true })}
className="mt-2"
id="edit-username"
value={resident.username}
disabled
className="mt-2 bg-muted"
/>
</div>
<div>
<Label htmlFor="edit-last">Last Name</Label>
<Label htmlFor="edit-doc-id">Resident ID</Label>
<Input
id="edit-last"
{...form.register('name_last', { required: true })}
id="edit-doc-id"
{...form.register('doc_id')}
className="mt-2"
/>
</div>
</div>
<div>
<Label htmlFor="edit-username">Username</Label>
<Input
id="edit-username"
value={resident.username}
disabled
className="mt-2 bg-muted"
/>
</div>
<div>
<Label htmlFor="edit-doc-id">Resident ID</Label>
<Input
id="edit-doc-id"
{...form.register('doc_id')}
className="mt-2"
/>
</div>
</div>
<DialogFooter>
<Button variant="outline" onClick={() => onOpenChange(false)}>
Cancel
</Button>
<Button
onClick={() =>
void form.handleSubmit((d) => void handleSave(d))()
}
variant="brand"
>
Save Changes
</Button>
</DialogFooter>
<DialogFooter>
<Button
variant="outline"
type="button"
onClick={() => onOpenChange(false)}
>
Cancel
</Button>
<Button type="submit" variant="brand">
Save Changes
</Button>
</DialogFooter>
</form>
</FormModal>
);
}
Expand Down Expand Up @@ -308,8 +325,10 @@ export function DeactivateDialog({
}: DeactivateDialogProps) {
const { toaster } = useToast();
const [loading, setLoading] = useState(false);
const displayId = resident.doc_id ?? '';
const confirm = useTypeToConfirm({ open, expected: displayId });
const { confirmToken, confirmLabel, confirm } = useConfirmToken(
resident,
open
);

const handleDeactivate = async () => {
setLoading(true);
Expand Down Expand Up @@ -391,8 +410,8 @@ export function DeactivateDialog({

<TonedPanel tone="orange">
<Label htmlFor="deactivate-confirm">
To confirm, type the Resident ID:{' '}
<strong>{displayId}</strong>
To confirm, type the {confirmLabel}:{' '}
<strong>{confirmToken}</strong>
</Label>
<Input
id="deactivate-confirm"
Expand Down Expand Up @@ -437,8 +456,10 @@ export function DeleteDialog({
}: DeleteDialogProps) {
const { toaster } = useToast();
const [loading, setLoading] = useState(false);
const displayId = resident.doc_id ?? '';
const confirm = useTypeToConfirm({ open, expected: displayId });
const { confirmToken, confirmLabel, confirm } = useConfirmToken(
resident,
open
);

const handleDelete = async () => {
setLoading(true);
Expand Down Expand Up @@ -477,8 +498,8 @@ export function DeleteDialog({

<TonedPanel tone="red">
<Label htmlFor="delete-confirm">
To confirm, type the Resident ID:{' '}
<strong>{displayId}</strong>
To confirm, type the {confirmLabel}:{' '}
<strong>{confirmToken}</strong>
</Label>
<Input
id="delete-confirm"
Expand Down Expand Up @@ -526,8 +547,10 @@ export function TransferDialog({
const { toaster } = useToast();
const [transferFacilityId, setTransferFacilityId] = useState('');
const [loading, setLoading] = useState(false);
const displayId = resident.doc_id ?? '';
const confirm = useTypeToConfirm({ open, expected: displayId });
const { confirmToken, confirmLabel, confirm } = useConfirmToken(
resident,
open
);

useEffect(() => {
if (!open) setTransferFacilityId('');
Expand Down Expand Up @@ -687,9 +710,9 @@ export function TransferDialog({
htmlFor="transfer-confirm"
className="text-sm font-medium"
>
Type{' '}
Type the {confirmLabel}{' '}
<span className="font-mono font-semibold text-brand-dark">
{displayId}
{confirmToken}
</span>{' '}
to confirm
</Label>
Expand Down
27 changes: 15 additions & 12 deletions frontend/src/pages/class-detail/BulkSessionFieldModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ interface BulkSessionFieldModalProps {
idPrefix: string;
options: FieldOption[];
payloadKey: string;
reasonOptions: Array<{ value: string; label: string }>;
reasonOptions: { value: string; label: string }[];
}

export function BulkSessionFieldModal({
Expand Down Expand Up @@ -87,12 +87,16 @@ export function BulkSessionFieldModal({
? [...sessions, ...futureSessions]
: sessions;

const { ok, fail } = await bulkPatchEvents(classId, allSessions, (s) => ({
date: s.date,
start_time: s.classTime?.split('-')[0],
is_cancelled: false,
[payloadKey]: Number(selectedId)
}));
const { ok, fail } = await bulkPatchEvents(
classId,
allSessions,
(s) => ({
date: s.date,
start_time: s.classTime?.split('-')[0],
is_cancelled: false,
[payloadKey]: Number(selectedId)
})
);

const selectedLabel =
options.find((o) => String(o.id) === selectedId)?.label ?? '';
Expand Down Expand Up @@ -133,7 +137,9 @@ export function BulkSessionFieldModal({
<Label htmlFor={fieldId}>New {subject}</Label>
<Select value={selectedId} onValueChange={setSelectedId}>
<SelectTrigger id={fieldId}>
<SelectValue placeholder={`Select ${subjectLower}`} />
<SelectValue
placeholder={`Select ${subjectLower}`}
/>
</SelectTrigger>
<SelectContent>
{options.map((opt) => (
Expand Down Expand Up @@ -180,10 +186,7 @@ export function BulkSessionFieldModal({
)}

{applyToFuture && futureSessions.length > 0 && (
<SessionList
sessions={futureSessions}
showDayName
/>
<SessionList sessions={futureSessions} showDayName />
)}

{useBulkLayout && sessions.length > 0 && (
Expand Down
Loading