feat: featured doctor toggle
This commit is contained in:
@@ -19,8 +19,8 @@ router.get('/getAll', getAllDoctors);
|
|||||||
router.get('/search', getDoctorsByDepartmentId);
|
router.get('/search', getDoctorsByDepartmentId);
|
||||||
router.get('/getTimings', getDoctorTimings);
|
router.get('/getTimings', getDoctorTimings);
|
||||||
router.get('/getTimings/:doctorId', getDoctorTimingById);
|
router.get('/getTimings/:doctorId', getDoctorTimingById);
|
||||||
router.get('/:doctorId', getDoctorByDoctorId);
|
|
||||||
router.get('/featured', getFeaturedDoctors);
|
router.get('/featured', getFeaturedDoctors);
|
||||||
|
router.get('/:doctorId', getDoctorByDoctorId);
|
||||||
|
|
||||||
router.post('/', jwtAuthMiddleware, createDoctor);
|
router.post('/', jwtAuthMiddleware, createDoctor);
|
||||||
router.patch('/:doctorId/:action', jwtAuthMiddleware, updateDoctor);
|
router.patch('/:doctorId/:action', jwtAuthMiddleware, updateDoctor);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ export interface Doctor {
|
|||||||
workingStatus?: string;
|
workingStatus?: string;
|
||||||
qualification?: string;
|
qualification?: string;
|
||||||
isActive: boolean;
|
isActive: boolean;
|
||||||
|
isFeatured: boolean;
|
||||||
globalSortOrder: number;
|
globalSortOrder: number;
|
||||||
|
|
||||||
departments?: {
|
departments?: {
|
||||||
@@ -53,7 +54,7 @@ export const createDoctorApi = async (data: Doctor) => {
|
|||||||
export const updateDoctorApi = async (
|
export const updateDoctorApi = async (
|
||||||
doctorId: string,
|
doctorId: string,
|
||||||
data: Partial<Doctor>,
|
data: Partial<Doctor>,
|
||||||
action: 'toggleStatus' | 'updateDetails' = 'updateDetails'
|
action: 'toggleStatus' | 'toggleFeatured' | 'updateDetails' = 'updateDetails'
|
||||||
) => {
|
) => {
|
||||||
try {
|
try {
|
||||||
const res = await apiClient.patch(`/doctors/${doctorId}/${action}`, data);
|
const res = await apiClient.patch(`/doctors/${doctorId}/${action}`, data);
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ export default function DoctorPage() {
|
|||||||
workingStatus: '',
|
workingStatus: '',
|
||||||
qualification: '',
|
qualification: '',
|
||||||
isActive: true,
|
isActive: true,
|
||||||
|
isFeatured: false,
|
||||||
globalSortOrder: 0,
|
globalSortOrder: 0,
|
||||||
departments: [],
|
departments: [],
|
||||||
professionalSummary: '',
|
professionalSummary: '',
|
||||||
@@ -156,6 +157,22 @@ export default function DoctorPage() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleToggleFeatured = async (doc: any) => {
|
||||||
|
try {
|
||||||
|
const newFeaturedStatus = !doc.isFeatured;
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
isFeatured: newFeaturedStatus,
|
||||||
|
};
|
||||||
|
|
||||||
|
await updateDoctorApi(doc.doctorId, payload, 'toggleFeatured');
|
||||||
|
|
||||||
|
fetchAll();
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Failed to update featured status', err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
function handleDepartmentToggle(depId: string) {
|
function handleDepartmentToggle(depId: string) {
|
||||||
const exists = form.departments.find((d: any) => d.departmentId === depId);
|
const exists = form.departments.find((d: any) => d.departmentId === depId);
|
||||||
if (exists) {
|
if (exists) {
|
||||||
@@ -201,6 +218,7 @@ export default function DoctorPage() {
|
|||||||
experience: '',
|
experience: '',
|
||||||
professionalSummary: '',
|
professionalSummary: '',
|
||||||
isActive: true,
|
isActive: true,
|
||||||
|
isFeatured: false,
|
||||||
globalSortOrder: 0,
|
globalSortOrder: 0,
|
||||||
specializations: [
|
specializations: [
|
||||||
{
|
{
|
||||||
@@ -235,6 +253,7 @@ export default function DoctorPage() {
|
|||||||
workingStatus: doc.workingStatus,
|
workingStatus: doc.workingStatus,
|
||||||
qualification: doc.qualification,
|
qualification: doc.qualification,
|
||||||
isActive: doc.isActive ?? true,
|
isActive: doc.isActive ?? true,
|
||||||
|
isFeatured: doc.isFeatured ?? false,
|
||||||
globalSortOrder: doc.globalSortOrder ?? 0,
|
globalSortOrder: doc.globalSortOrder ?? 0,
|
||||||
experience: doc.experience || '',
|
experience: doc.experience || '',
|
||||||
professionalSummary: doc.professionalSummary || '',
|
professionalSummary: doc.professionalSummary || '',
|
||||||
@@ -353,14 +372,15 @@ export default function DoctorPage() {
|
|||||||
|
|
||||||
<CardContent className="p-0 sm:p-6 space-y-4">
|
<CardContent className="p-0 sm:p-6 space-y-4">
|
||||||
<div className="rounded-md border overflow-x-auto overflow-y-auto max-h-[650px] relative">
|
<div className="rounded-md border overflow-x-auto overflow-y-auto max-h-[650px] relative">
|
||||||
<Table className="w-full min-w-[1100px] table-fixed border-separate border-spacing-0">
|
<Table className="w-full min-w-[1200px] table-fixed border-separate border-spacing-0">
|
||||||
<TableHeader className="sticky top-0 z-20 bg-background shadow-sm">
|
<TableHeader className="sticky top-0 z-20 bg-background shadow-sm">
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableHead className="w-[80px] bg-background text-sm font-bold">Priority </TableHead>
|
<TableHead className="w-[80px] bg-background text-sm font-bold">Priority </TableHead>
|
||||||
<TableHead className="w-[180px] bg-background text-sm font-bold">Doctor Info</TableHead>
|
<TableHead className="w-[180px] bg-background text-sm font-bold">Doctor Info</TableHead>
|
||||||
<TableHead className="w-[150px] bg-background text-sm font-bold">Designation</TableHead>
|
<TableHead className="w-[150px] bg-background text-sm font-bold">Designation</TableHead>
|
||||||
<TableHead className="w-[220px] bg-background text-sm font-bold">Departments (Hierarchy)</TableHead>
|
<TableHead className="w-[220px] bg-background text-sm font-bold">Departments (Hierarchy)</TableHead>
|
||||||
<TableHead className="w-[80px] bg-background text-sm font-bold">Status (Active)</TableHead>
|
<TableHead className="w-[100px] bg-background text-sm font-bold">Status (Active)</TableHead>
|
||||||
|
<TableHead className="w-[100px] bg-background text-sm font-bold">Featured</TableHead>
|
||||||
<TableHead className="w-[80px] bg-background text-right text-sm font-bold">Actions</TableHead>
|
<TableHead className="w-[80px] bg-background text-right text-sm font-bold">Actions</TableHead>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHeader>
|
</TableHeader>
|
||||||
@@ -368,13 +388,13 @@ export default function DoctorPage() {
|
|||||||
<TableBody>
|
<TableBody>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell colSpan={6} className="text-center py-10">
|
<TableCell colSpan={7} className="text-center py-10">
|
||||||
<Loader2 className="h-8 w-8 animate-spin mx-auto" />
|
<Loader2 className="h-8 w-8 animate-spin mx-auto" />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
) : currentItems.length === 0 ? (
|
) : currentItems.length === 0 ? (
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell colSpan={6} className="text-center text-muted-foreground py-10 text-base">
|
<TableCell colSpan={7} className="text-center text-muted-foreground py-10 text-base">
|
||||||
No doctors found
|
No doctors found
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
@@ -423,6 +443,15 @@ export default function DoctorPage() {
|
|||||||
</div>
|
</div>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
|
||||||
|
<TableCell>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Switch checked={doc.isFeatured || false} onCheckedChange={() => handleToggleFeatured(doc)} />
|
||||||
|
<Badge variant={doc.isFeatured ? 'default' : 'secondary'}>
|
||||||
|
{doc.isFeatured ? 'Featured' : 'Hidden'}
|
||||||
|
</Badge>
|
||||||
|
</div>
|
||||||
|
</TableCell>
|
||||||
|
|
||||||
<TableCell className="text-right">
|
<TableCell className="text-right">
|
||||||
<div className="flex justify-end gap-2">
|
<div className="flex justify-end gap-2">
|
||||||
<Button size="icon" variant="ghost" className="h-9 w-9" onClick={() => handlePreview(doc)}>
|
<Button size="icon" variant="ghost" className="h-9 w-9" onClick={() => handlePreview(doc)}>
|
||||||
@@ -508,6 +537,17 @@ export default function DoctorPage() {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="flex items-center justify-between p-3 border rounded-md bg-muted/30">
|
||||||
|
<Label htmlFor="isFeatured" className="text-base font-semibold cursor-pointer">
|
||||||
|
Featured
|
||||||
|
</Label>
|
||||||
|
<Switch
|
||||||
|
id="isFeatured"
|
||||||
|
checked={form.isFeatured}
|
||||||
|
onCheckedChange={(val) => setForm({ ...form, isFeatured: val })}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
<Label htmlFor="globalSortOrder" className="text-sm font-semibold">
|
<Label htmlFor="globalSortOrder" className="text-sm font-semibold">
|
||||||
Sort Priority (Lower numbers show first)
|
Sort Priority (Lower numbers show first)
|
||||||
|
|||||||
Reference in New Issue
Block a user