import type { ReactNode } from "react";
import { useState } from "react";
import { clinicianApi } from "../../api/client";
import type { ContextRecord, RecordType } from "../../api/types";
import { recordTypes } from "../../logic/records";
import { areaClass, Button, cn, fieldClass, Icon, labelClass, Modal } from "../kit";
import { errorText } from "../ui";
const Actions = ({ children }: { children: ReactNode }) => <div className="flex flex-wrap justify-end gap-2 pt-1">{children}</div>;
export function PasteNote({ open, onClose, onAdd }: { open: boolean; onClose: () => void; onAdd: (text: string, title: string) => void }) {
const [text, setText] = useState("");
const [title, setTitle] = useState("Clinic note");
// Cancel forgets what was typed, so a note never comes back by mistake.
const close = () => {
setText("");
setTitle("Clinic note");
onClose();
};
return (
<Modal open={open} title="Paste or type a note" onClose={close}>
<label className={labelClass}>
Title
<input className={fieldClass} value={title} onChange={(e) => setTitle(e.target.value)} />
</label>
<label className={labelClass}>
Note
<textarea className={areaClass} rows={8} value={text} placeholder="Paste a prescription, result or clinic note. Keep units and dates." onChange={(e) => setText(e.target.value)} />
</label>
<small className={cn("-mt-2 font-mono text-[11.5px] tabular-nums", text.length > 12000 ? "text-red-text" : "text-muted")}>{text.length.toLocaleString("en")} of 12,000 characters</small>
<Actions>
<Button variant="ghost" onClick={close}>
Cancel
</Button>
<Button variant="primary" disabled={!text.trim()} onClick={() => { onAdd(text.trim(), title.trim() || "Clinic note"); setText(""); }}>
Add to the list
</Button>
</Actions>
</Modal>
);
}
export function EditRecord({ record, onClose, onSaved }: { record: ContextRecord | null; onClose: () => void; onSaved: () => void }) {
const [form, setForm] = useState({ title: "", type: "other" as RecordType, place: "", recordDate: "" });
const [error, setError] = useState("");
const [loadedFor, setLoadedFor] = useState<string | null>(null);
if (record && loadedFor !== record.id) {
setLoadedFor(record.id);
setForm({ title: record.title, type: record.type, place: record.place ?? "", recordDate: record.recordDate ?? "" });
}
const save = async () => {
if (!record) return;
try {
await clinicianApi.updateRecord(record.id, { title: form.title.trim(), type: form.type, place: form.place.trim() || null, recordDate: form.recordDate || null });
onSaved();
} catch (e) {
setError(errorText(e));
}
};
return (
<Modal open={!!record} title="Record details" onClose={onClose}>
<label className={labelClass}>
Title
<input className={fieldClass} value={form.title} maxLength={120} onChange={(e) => setForm({ ...form, title: e.target.value })} />
</label>
<label className={labelClass}>
Type
<select className={cn(fieldClass, "pr-8")} value={form.type} onChange={(e) => setForm({ ...form, type: e.target.value as RecordType })}>
{Object.entries(recordTypes).map(([v, l]) => (
<option key={v} value={v}>
{l}
</option>
))}
</select>
</label>
<label className={labelClass}>
Where it came from
<input className={fieldClass} value={form.place} maxLength={120} onChange={(e) => setForm({ ...form, place: e.target.value })} />
</label>
<label className={labelClass}>
Date on the record
<input className={fieldClass} type="date" value={form.recordDate} onChange={(e) => setForm({ ...form, recordDate: e.target.value })} />
</label>
{error && (
<p className="m-0 text-[12.5px] font-medium text-red-text" role="alert">
{error}
</p>
)}
<Actions>
<Button variant="ghost" onClick={onClose}>
Cancel
</Button>
<Button variant="primary" onClick={() => void save()}>
Save
</Button>
</Actions>
</Modal>
);
}
/** The confirm step before a record is removed: what happens to its facts, and that it is logged. */
export function RemoveRecord({ record, onClose, onRemove }: { record: ContextRecord | null; onClose: () => void; onRemove: (record: ContextRecord) => void }) {
return (
<Modal open={!!record} title="Remove this record?" onClose={onClose}>
{record && (
<>
<div className="flex items-start gap-3.5">
<span aria-hidden="true" className="flex size-9 shrink-0 items-center justify-center rounded-[10px] bg-red-fill text-red-icon">
<Icon name="delete-bin-line" size={18} />
</span>
<div className="flex min-w-0 flex-col gap-1.5 text-[13.5px] leading-5 text-body">
<p className="m-0">
<b className="font-semibold text-ink">{record.title}</b> will be removed from this patient's records. Its facts leave review and the next check, and the
records left are read again.
</p>
<p className="m-0 text-[13px] text-muted">Past checks keep the lines they used. The removal is recorded in the patient's Activity.</p>
</div>
</div>
<Actions>
<Button variant="quiet" onClick={onClose}>
Cancel
</Button>
<Button variant="red" onClick={() => onRemove(record)}>
<Icon name="delete-bin-line" size={15} /> Remove record
</Button>
</Actions>
</>
)}
</Modal>
);
}