feat(clinic): add image deletion functionality with confirmation dialog
This commit is contained in:
@@ -52,11 +52,12 @@ export default function BlogFormPage() {
|
||||
|
||||
const { data, isLoading } = useQuery({
|
||||
queryKey: ['blog', uuid],
|
||||
queryFn: () => api.get<ApiResponse<Blog>>(`/api/v1/blog/${uuid}`),
|
||||
queryFn: () => api.get<ApiResponse<{ data: Blog }>>(`/api/v1/blog/${uuid}`),
|
||||
enabled: isEdit,
|
||||
});
|
||||
|
||||
const blog = data?.data;
|
||||
// detail endpoint is double-nested: success(['data' => $blog->toArray()])
|
||||
const blog = data?.data?.data;
|
||||
|
||||
const { register, handleSubmit, control, watch, setValue, formState: { errors, isSubmitting } } = useForm<FormData>({
|
||||
resolver: zodResolver(schema),
|
||||
@@ -178,6 +179,7 @@ export default function BlogFormPage() {
|
||||
field.onChange(editor.getData())
|
||||
}
|
||||
config={{
|
||||
licenseKey: 'GPL',
|
||||
language: 'fa',
|
||||
toolbar: [
|
||||
'heading', '|',
|
||||
|
||||
@@ -479,6 +479,7 @@ export default function ClinicDetailPage() {
|
||||
const [addrFormOpen, setAddrFormOpen] = useState(false);
|
||||
const [editingClinicAddr, setEditingClinicAddr] = useState<ClinicAddress | null>(null);
|
||||
const [deleteAddrConfirm, setDeleteAddrConfirm] = useState<ClinicAddress | null>(null);
|
||||
const [deleteImageConfirm, setDeleteImageConfirm] = useState<string | null>(null);
|
||||
|
||||
const emptyAddrForm = { name: '', address: '', telephone: '', province_id: null as number | null, city_id: null as number | null, latitude: null as number | null, longitude: null as number | null };
|
||||
const [addrForm, setAddrForm] = useState(emptyAddrForm);
|
||||
@@ -636,6 +637,16 @@ export default function ClinicDetailPage() {
|
||||
finally { setGalleryUploading(false); }
|
||||
};
|
||||
|
||||
const handleGalleryRemove = async (url: string) => {
|
||||
if (!clinic) return;
|
||||
try {
|
||||
const remaining = (clinic.images_clinic ?? []).filter(img => img?.url && img.url !== url);
|
||||
await api.patch(`/api/v1/clinic/${uuid}`, { image_clinic: remaining });
|
||||
toast.success('تصویر حذف شد');
|
||||
qc.invalidateQueries({ queryKey: ['clinic-detail', uuid] });
|
||||
} catch (e: any) { toast.error(e?.message ?? 'خطا در حذف تصویر'); }
|
||||
};
|
||||
|
||||
const hue = HUES_LIST[(uuid?.charCodeAt(0) ?? 0) % HUES_LIST.length];
|
||||
const logo = clinic?.logo ?? clinic?.clinic_logo;
|
||||
// شهر و استان از آدرس DoctorAddress (منبع واقعی) نه از Clinic entity
|
||||
@@ -915,8 +926,17 @@ export default function ClinicDetailPage() {
|
||||
) : (
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(110px, 1fr))', gap: 8 }}>
|
||||
{clinic.images_clinic.filter(img => img?.url).map((img, i) => (
|
||||
<div key={i} style={{ borderRadius: 8, overflow: 'hidden', aspectRatio: '1', background: 'var(--surface-2, var(--bg))' }}>
|
||||
<div key={i} style={{ position: 'relative', borderRadius: 8, overflow: 'hidden', aspectRatio: '1', background: 'var(--surface-2, var(--bg))' }}>
|
||||
<img src={img.url} alt="" style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
|
||||
<button
|
||||
type="button"
|
||||
className="mini-btn danger"
|
||||
title="حذف تصویر"
|
||||
onClick={() => setDeleteImageConfirm(img.url)}
|
||||
style={{ position: 'absolute', top: 6, left: 6 }}
|
||||
>
|
||||
<TrashIcon style={{ width: 14, height: 14 }} />
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
@@ -1161,6 +1181,20 @@ export default function ClinicDetailPage() {
|
||||
onCancel={() => setDeleteAddrConfirm(null)}
|
||||
/>
|
||||
|
||||
{/* Delete Gallery Image Confirm */}
|
||||
<ConfirmDialog
|
||||
open={deleteImageConfirm !== null}
|
||||
title="حذف تصویر"
|
||||
message="آیا از حذف این تصویر از گالری اطمینان دارید؟"
|
||||
confirmLabel="حذف"
|
||||
danger
|
||||
onConfirm={() => {
|
||||
if (deleteImageConfirm) handleGalleryRemove(deleteImageConfirm);
|
||||
setDeleteImageConfirm(null);
|
||||
}}
|
||||
onCancel={() => setDeleteImageConfirm(null)}
|
||||
/>
|
||||
|
||||
{/* Edit modal — portal to escape Leaflet transform context */}
|
||||
{editOpen && createPortal(
|
||||
<EditModal
|
||||
|
||||
Reference in New Issue
Block a user