theming, date, time localisation, additional features, seeding initial cleanup
This commit is contained in:
@@ -10,6 +10,7 @@ import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from
|
||||
import { Switch } from '@/components/ui/switch';
|
||||
import { Plus, Edit, Trash2, Clock } from 'lucide-react';
|
||||
import { useToast } from '@/hooks/use-toast';
|
||||
import { getWeekDays } from '@/lib/utils';
|
||||
|
||||
interface TimeSlot {
|
||||
id: string;
|
||||
@@ -21,7 +22,9 @@ interface TimeSlot {
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
const DAYS = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
|
||||
// Use Irish week order (Monday first)
|
||||
const DAYS = getWeekDays().map((day) => day.label);
|
||||
const IRISH_DAY_ORDER = [1, 2, 3, 4, 5, 6, 0]; // Monday-Sunday in JS getDay() values
|
||||
|
||||
export function AdminTimeSlotManagement() {
|
||||
const [timeSlots, setTimeSlots] = useState<TimeSlot[]>([]);
|
||||
@@ -29,7 +32,7 @@ export function AdminTimeSlotManagement() {
|
||||
const [showDialog, setShowDialog] = useState(false);
|
||||
const [editingSlot, setEditingSlot] = useState<TimeSlot | null>(null);
|
||||
const [formData, setFormData] = useState({
|
||||
dayOfWeek: 0,
|
||||
dayOfWeek: 1, // Default to Monday (Irish standard)
|
||||
startTime: '',
|
||||
endTime: '',
|
||||
isActive: true,
|
||||
@@ -208,7 +211,7 @@ export function AdminTimeSlotManagement() {
|
||||
const resetForm = () => {
|
||||
setEditingSlot(null);
|
||||
setFormData({
|
||||
dayOfWeek: 0,
|
||||
dayOfWeek: 1, // Default to Monday (Irish standard)
|
||||
startTime: '',
|
||||
endTime: '',
|
||||
isActive: true,
|
||||
@@ -255,9 +258,9 @@ export function AdminTimeSlotManagement() {
|
||||
<SelectValue placeholder='Select day' />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{DAYS.map((day, index) => (
|
||||
<SelectItem key={index} value={index.toString()}>
|
||||
{day}
|
||||
{IRISH_DAY_ORDER.map((jsDayOfWeek, displayIndex) => (
|
||||
<SelectItem key={jsDayOfWeek} value={jsDayOfWeek.toString()}>
|
||||
{DAYS[displayIndex]}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
@@ -309,75 +312,80 @@ export function AdminTimeSlotManagement() {
|
||||
<div className='text-center py-4'>Loading time slots...</div>
|
||||
) : (
|
||||
<div className='space-y-6'>
|
||||
{DAYS.map((day, dayIndex) => (
|
||||
<div key={dayIndex} className='space-y-2'>
|
||||
<div className='flex justify-between items-center'>
|
||||
<h3 className='font-semibold text-lg'>{day}</h3>
|
||||
{groupedTimeSlots[dayIndex]?.length > 0 && (
|
||||
<Button
|
||||
size='sm'
|
||||
variant='outline'
|
||||
onClick={() => handleWipeDay(dayIndex)}
|
||||
className='text-red-600 hover:text-red-700 hover:bg-red-50'
|
||||
disabled={loading}
|
||||
>
|
||||
<Trash2 className='h-4 w-4 mr-1' />
|
||||
Wipe All
|
||||
</Button>
|
||||
{IRISH_DAY_ORDER.map((jsDayOfWeek, displayIndex) => {
|
||||
const dayName = DAYS[displayIndex];
|
||||
return (
|
||||
<div key={jsDayOfWeek} className='space-y-2'>
|
||||
<div className='flex justify-between items-center'>
|
||||
<h3 className='font-semibold text-lg'>{dayName}</h3>
|
||||
{groupedTimeSlots[jsDayOfWeek]?.length > 0 && (
|
||||
<Button
|
||||
size='sm'
|
||||
variant='outline'
|
||||
onClick={() => handleWipeDay(jsDayOfWeek)}
|
||||
className='text-destructive hover:text-destructive/80 hover:bg-destructive/10'
|
||||
disabled={loading}
|
||||
>
|
||||
<Trash2 className='h-4 w-4 mr-1' />
|
||||
Wipe All
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
{groupedTimeSlots[jsDayOfWeek]?.length > 0 ? (
|
||||
<div className='grid gap-2'>
|
||||
{groupedTimeSlots[jsDayOfWeek]
|
||||
.sort((a, b) => a.startTime.localeCompare(b.startTime))
|
||||
.map((slot) => (
|
||||
<div
|
||||
key={slot.id}
|
||||
className={`flex items-center justify-between p-3 border rounded-lg ${
|
||||
slot.isActive
|
||||
? 'bg-green-50 border-green-200 dark:bg-green-950 dark:border-green-800'
|
||||
: 'bg-muted border-border'
|
||||
}`}
|
||||
>
|
||||
<div className='flex items-center space-x-3'>
|
||||
<div className='font-medium'>
|
||||
{slot.startTime} - {slot.endTime}
|
||||
</div>
|
||||
<div
|
||||
className={`px-2 py-1 rounded-full text-xs ${
|
||||
slot.isActive
|
||||
? 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200'
|
||||
: 'bg-muted text-muted-foreground'
|
||||
}`}
|
||||
>
|
||||
{slot.isActive ? 'Active' : 'Inactive'}
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex space-x-2'>
|
||||
<Button
|
||||
size='sm'
|
||||
variant='outline'
|
||||
onClick={() => handleEdit(slot)}
|
||||
>
|
||||
<Edit className='h-4 w-4' />
|
||||
</Button>
|
||||
<Button
|
||||
size='sm'
|
||||
variant='outline'
|
||||
onClick={() => handleDelete(slot.id)}
|
||||
className='text-destructive hover:text-destructive/80'
|
||||
>
|
||||
<Trash2 className='h-4 w-4' />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<p className='text-muted-foreground italic'>
|
||||
No time slots configured for {dayName}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
{groupedTimeSlots[dayIndex]?.length > 0 ? (
|
||||
<div className='grid gap-2'>
|
||||
{groupedTimeSlots[dayIndex]
|
||||
.sort((a, b) => a.startTime.localeCompare(b.startTime))
|
||||
.map((slot) => (
|
||||
<div
|
||||
key={slot.id}
|
||||
className={`flex items-center justify-between p-3 border rounded-lg ${
|
||||
slot.isActive
|
||||
? 'bg-green-50 border-green-200'
|
||||
: 'bg-gray-50 border-gray-200'
|
||||
}`}
|
||||
>
|
||||
<div className='flex items-center space-x-3'>
|
||||
<div className='font-medium'>
|
||||
{slot.startTime} - {slot.endTime}
|
||||
</div>
|
||||
<div
|
||||
className={`px-2 py-1 rounded-full text-xs ${
|
||||
slot.isActive
|
||||
? 'bg-green-100 text-green-800'
|
||||
: 'bg-gray-100 text-gray-800'
|
||||
}`}
|
||||
>
|
||||
{slot.isActive ? 'Active' : 'Inactive'}
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex space-x-2'>
|
||||
<Button
|
||||
size='sm'
|
||||
variant='outline'
|
||||
onClick={() => handleEdit(slot)}
|
||||
>
|
||||
<Edit className='h-4 w-4' />
|
||||
</Button>
|
||||
<Button
|
||||
size='sm'
|
||||
variant='outline'
|
||||
onClick={() => handleDelete(slot.id)}
|
||||
className='text-red-600 hover:text-red-700'
|
||||
>
|
||||
<Trash2 className='h-4 w-4' />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<p className='text-gray-500 italic'>No time slots configured for {day}</p>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
|
||||
Reference in New Issue
Block a user