feat(resources): one tabbed page per resource
In the resource-first model a resource is the unit of capacity, so its
working hours, holidays, services, skills and categories belong to it — not
scattered across a list page's modals plus a separate calendar page.
/admin/resources/{uuid} now carries six tabs and the active tab lives in the
query string, so back and refresh land on the same view. The old
/calendar URL redirects to ?tab=hours instead of 404ing.
The skills and services modal bodies became panels the tab renders directly;
the modals are now thin wrappers, so the list page keeps working unchanged
and there is still one implementation of each editor.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -70,10 +70,22 @@ export function useResources(filters: ResourceFilters = {}) {
|
||||
onError: (e) => fail(e, 'ذخیرهٔ مهارتها ناموفق بود'),
|
||||
});
|
||||
|
||||
/** دستهٔ منبع از کاتالوگ سراسری میآید؛ ساختنش فقط در «تنظیمات ← دستهبندیها» ممکن است. */
|
||||
const setCategories = useMutation({
|
||||
mutationFn: ({ uuid, categoryUuids }: { uuid: string; categoryUuids: string[] }) =>
|
||||
api.put<ApiResponse<ClinicResource>>(`/api/v1/resource/${uuid}/categories`, { category_uuids: categoryUuids }),
|
||||
onSuccess: () => {
|
||||
toast.success('دستهبندیهای منبع ذخیره شد');
|
||||
invalidate();
|
||||
qc.invalidateQueries({ queryKey: ['resource-detail'] });
|
||||
},
|
||||
onError: (e) => fail(e, 'ذخیرهٔ دستهبندیها ناموفق بود'),
|
||||
});
|
||||
|
||||
return {
|
||||
resources: query.data?.data ?? [],
|
||||
loading: query.isLoading,
|
||||
create, update, remove, setSkills,
|
||||
create, update, remove, setSkills, setCategories,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user