improve planning
This commit is contained in:
parent
4476a76180
commit
5d29201552
3 changed files with 89 additions and 37 deletions
|
|
@ -237,3 +237,18 @@ export const useDeleteTablo = () => {
|
|||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useGetAllTabloAccess = () => {
|
||||
const user = useUser();
|
||||
const { data, isLoading, error } = useQuery({
|
||||
queryKey: ["tablo-access", user.id],
|
||||
queryFn: async () => {
|
||||
const { data } = await supabase
|
||||
.from("tablo_access")
|
||||
.select("*")
|
||||
.eq("user_id", user.id);
|
||||
return data;
|
||||
},
|
||||
});
|
||||
return { data, isLoading, error };
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { useState, useEffect } from "react";
|
||||
import { useTablosList } from "@ui/hooks/tablos";
|
||||
import { useGetAllTabloAccess, useTablosList } from "@ui/hooks/tablos";
|
||||
import { useEventsByTablo, useDeleteEvent } from "@ui/hooks/events";
|
||||
import {
|
||||
Select,
|
||||
|
|
@ -13,6 +13,7 @@ import { generateICSFromEvents, downloadICSFile } from "@ui/utils/helpers";
|
|||
import { ImportICSModal } from "@ui/components/ImportICSModal";
|
||||
import { WebcalModal } from "@ui/components/WebcalModal";
|
||||
import { FolderInputIcon, PlusIcon } from "lucide-react";
|
||||
import { EventAndTablo } from "@ui/types/events.types";
|
||||
|
||||
type ViewType = "month" | "week" | "day";
|
||||
|
||||
|
|
@ -34,9 +35,23 @@ export const PlanningPage = () => {
|
|||
// Fetch events for selected tablo or all tablos
|
||||
const { data: tabloEvents = [], isLoading: tabloEventsLoading } =
|
||||
useEventsByTablo(selectedTabloId !== "all" ? selectedTabloId : null);
|
||||
// Fetch all tablo accesses
|
||||
const { data: tabloAccess } = useGetAllTabloAccess();
|
||||
|
||||
const deleteEvent = useDeleteEvent();
|
||||
|
||||
// Check if an event can be deleted (e.g., based on permissions, event status, etc.)
|
||||
const canDeleteEvent = (event: EventAndTablo) => {
|
||||
if (
|
||||
tabloAccess?.find(
|
||||
(access) => access.tablo_id === event.tablo_id && access.is_admin
|
||||
)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// Keyboard shortcuts for view switching
|
||||
useEffect(() => {
|
||||
const handleKeyPress = (event: KeyboardEvent) => {
|
||||
|
|
@ -251,12 +266,13 @@ export const PlanningPage = () => {
|
|||
} ${startOfWeek.getFullYear()}`;
|
||||
}
|
||||
} else {
|
||||
return currentDate.toLocaleDateString("fr-FR", {
|
||||
const dateString = currentDate.toLocaleDateString("fr-FR", {
|
||||
weekday: "long",
|
||||
year: "numeric",
|
||||
month: "long",
|
||||
day: "numeric",
|
||||
});
|
||||
return dateString.charAt(0).toUpperCase() + dateString.slice(1);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -359,11 +375,12 @@ export const PlanningPage = () => {
|
|||
</div>
|
||||
<div className="space-y-1">
|
||||
{getEventsForDate(day)
|
||||
.sort((a, b) => a.start_time.localeCompare(b.start_time))
|
||||
.slice(0, 3)
|
||||
.map((event) => (
|
||||
<div
|
||||
key={event.event_id}
|
||||
className={`text-[10px] px-1.5 py-0.5 rounded text-white ${event.tablo_color} truncate cursor-pointer hover:opacity-80 group relative leading-tight`}
|
||||
className={`text-[10px] px-1.5 py-1 rounded text-white ${event.tablo_color} truncate cursor-pointer hover:opacity-80 group relative leading-tight`}
|
||||
title={`${formatTime(event.start_time)} ${event.title}${
|
||||
selectedTabloId === "all" && event.tablo_name
|
||||
? ` - ${event.tablo_name}`
|
||||
|
|
@ -388,16 +405,18 @@ export const PlanningPage = () => {
|
|||
</span>
|
||||
)}
|
||||
</div>
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
deleteEvent.mutate(event.event_id);
|
||||
}}
|
||||
className="absolute -top-1 -right-1 w-5 h-5 bg-red-500 text-white rounded-full opacity-0 group-hover:opacity-100 transition-all text-sm flex items-center justify-center hover:bg-red-600 hover:scale-110 shadow-sm"
|
||||
title="Supprimer l'événement"
|
||||
>
|
||||
×
|
||||
</button>
|
||||
{canDeleteEvent(event) && (
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
deleteEvent.mutate(event.event_id);
|
||||
}}
|
||||
className="absolute -top-1 -right-1 w-5 h-5 bg-red-500 text-white rounded-full opacity-0 group-hover:opacity-100 transition-all text-sm flex items-center justify-center hover:bg-red-600 hover:scale-110 shadow-sm"
|
||||
title="Supprimer l'événement"
|
||||
>
|
||||
×
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
{getEventsForDate(day).length > 3 && (
|
||||
|
|
@ -499,11 +518,18 @@ export const PlanningPage = () => {
|
|||
height: `${eventHeight}px`,
|
||||
minHeight: "30px",
|
||||
}}
|
||||
title={`${formatTime(event.start_time)} - ${formatTime(
|
||||
event.end_time
|
||||
)} ${event.title}${
|
||||
selectedTabloId === "all" && event.tablo_name
|
||||
? ` - ${event.tablo_name}`
|
||||
: ""
|
||||
}`}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
<div className="text-[10px] font-medium truncate leading-tight">
|
||||
<div className="text-[10px] font-medium leading-tight">
|
||||
{event.title}
|
||||
{selectedTabloId === "all" && event.tablo_name && (
|
||||
<span className="opacity-75 ml-1">
|
||||
|
|
@ -517,16 +543,18 @@ export const PlanningPage = () => {
|
|||
{formatTime(event.end_time)}
|
||||
</div>
|
||||
)}
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
deleteEvent.mutate(event.event_id);
|
||||
}}
|
||||
className="absolute -top-1 -right-1 w-4 h-4 bg-red-500 text-white rounded-full opacity-0 group-hover:opacity-100 transition-all text-xs flex items-center justify-center hover:bg-red-600 hover:scale-110 shadow-sm z-30"
|
||||
title="Supprimer l'événement"
|
||||
>
|
||||
×
|
||||
</button>
|
||||
{canDeleteEvent(event) && (
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
deleteEvent.mutate(event.event_id);
|
||||
}}
|
||||
className="absolute -top-1 -right-1 w-5 h-5 bg-red-500 text-white rounded-full opacity-0 group-hover:opacity-100 transition-all text-sm flex items-center justify-center hover:bg-red-600 hover:scale-110 shadow-sm"
|
||||
title="Supprimer l'événement"
|
||||
>
|
||||
×
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
|
@ -601,6 +629,13 @@ export const PlanningPage = () => {
|
|||
height: `${eventHeight}px`,
|
||||
minHeight: "30px",
|
||||
}}
|
||||
title={`${formatTime(event.start_time)} - ${formatTime(
|
||||
event.end_time
|
||||
)} ${event.title}${
|
||||
selectedTabloId === "all" && event.tablo_name
|
||||
? ` - ${event.tablo_name}`
|
||||
: ""
|
||||
}`}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
}}
|
||||
|
|
@ -624,16 +659,18 @@ export const PlanningPage = () => {
|
|||
{event.description}
|
||||
</div>
|
||||
)}
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
deleteEvent.mutate(event.event_id);
|
||||
}}
|
||||
className="absolute -top-1 -right-1 w-4 h-4 bg-red-500 text-white rounded-full opacity-0 group-hover:opacity-100 transition-all text-xs flex items-center justify-center hover:bg-red-600 hover:scale-110 shadow-sm z-30"
|
||||
title="Supprimer l'événement"
|
||||
>
|
||||
×
|
||||
</button>
|
||||
{canDeleteEvent(event) && (
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
deleteEvent.mutate(event.event_id);
|
||||
}}
|
||||
className="absolute -top-1 -right-1 w-5 h-5 bg-red-500 text-white rounded-full opacity-0 group-hover:opacity-100 transition-all text-sm flex items-center justify-center hover:bg-red-600 hover:scale-110 shadow-sm"
|
||||
title="Supprimer l'événement"
|
||||
>
|
||||
×
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
|
@ -800,9 +837,9 @@ export const PlanningPage = () => {
|
|||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<h2 className="text-xl font-medium text-gray-900 dark:text-white">
|
||||
<h3 className="text-lg font-medium text-gray-900 dark:text-white">
|
||||
{getViewTitle()}
|
||||
</h2>
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center space-x-2">
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { useSession } from "@ui/contexts/SessionContext";
|
|||
import { api } from "@ui/lib/api";
|
||||
import { LoadingSpinner } from "@ui/components/LoadingSpinner";
|
||||
|
||||
type User = Tables<"profiles"> & {
|
||||
export type User = Tables<"profiles"> & {
|
||||
streamToken: string | null;
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue