diff --git a/apps/main/src/pages/PublicBookingPage.tsx b/apps/main/src/pages/PublicBookingPage.tsx
index 6e86861..6d6db6e 100644
--- a/apps/main/src/pages/PublicBookingPage.tsx
+++ b/apps/main/src/pages/PublicBookingPage.tsx
@@ -11,7 +11,12 @@ import { Button } from "@xtablo/ui/components/button";
import { FieldError } from "@xtablo/ui/components/field";
import { Input } from "@xtablo/ui/components/input";
import { Label } from "@xtablo/ui/components/label";
-import { Strong, Text } from "@xtablo/ui/components/typography";
+import {
+ Text,
+ TypographyH3,
+ TypographyH4,
+ TypographyMuted,
+} from "@xtablo/ui/components/typography";
import {
CalendarIcon,
ChevronLeftIcon,
@@ -25,6 +30,7 @@ import {
} from "lucide-react";
import { useState } from "react";
import { useNavigate, useParams } from "react-router-dom";
+import { twMerge } from "tailwind-merge";
import { api } from "../lib/api";
import { supabase } from "../lib/supabase";
import { useMaybeUser } from "../providers/UserStoreProvider";
@@ -81,13 +87,7 @@ export function PublicBookingPage() {
const { theme, setTheme } = useTheme();
const toggleTheme = () => {
- if (theme === "light") {
- setTheme("dark");
- } else if (theme === "dark") {
- setTheme("system");
- } else {
- setTheme("light");
- }
+ setTheme(theme === "light" ? "dark" : "light");
};
const getThemeIcon = () => {
@@ -321,244 +321,246 @@ export function PublicBookingPage() {
};
return (
-
- {/* Header */}
-
-
-
- {/* Xtablo Logo */}
-
-

-
-
- {/* Avatar */}
- {/*
- {userProfile.avatar_url ? (
-

- ) : (
-
-
-
- )}
-
*/}
-
- {/* User Info */}
-
-
- {userProfile?.name || "Professionnel"}
-
-
-
- {/* Theme Toggle */}
-
-
-
-
+
+
+ {/* Theme Toggle - Floating */}
+
+
-
- {/* Main Content */}
-
-
- {/* Left Sidebar - Event Type Info */}
-
-
-
- {eventType?.name || "Type d'appel"}
-
+ {/* Main Card */}
+
+
+ {/* Left Panel - User Profile & Event Details */}
+
+ {/* Subtle accent overlay */}
+
- {eventType?.description && (
-
- {eventType.description}
-
- )}
-
-
- {eventType?.duration && (
-
-
-
-
- Durée: {formatDuration(eventType.duration)}
-
+
+ {/* User Profile */}
+
+ {userProfile?.avatar_url ? (
+

+ ) : (
+
+
-
- )}
-
- {eventType?.price && (
-
-
- €
-
-
-
- {eventType.price}€
-
-
-
- )}
- {eventType?.location && (
-
-
-
-
- {eventType.location}
-
-
-
- )}
- {eventType?.requiresApproval && (
-
-
-
-
- Approbation requise
-
-
-
- )}
-
-
-
-
- {/* Center - Calendar */}
-
-
- {/* Calendar Header */}
-
-
- {formatMonthYear(currentDate)}
-
-
-
-
+ )}
+
+ {userProfile?.name || "Professionnel"}
+
-
- {/* Calendar Grid */}
-
- {["Lun", "Mar", "Mer", "Jeu", "Ven", "Sam", "Dim"].map((day) => (
-
- {day}
-
- ))}
-
+ {/* Event Type Info */}
+
+
+ {eventType?.name || "Type d'appel"}
+
-
- {getDaysInMonth(currentDate).map((date, index) => (
-
- {date ? (
-
- ) : (
-
+ {eventType?.description && (
+
+ {eventType.description}
+
+ )}
+
+
+ {eventType?.duration && (
+
+
+
+
+
+
Durée
+
+ {formatDuration(eventType.duration)}
+
+
+
+ )}
+
+ {eventType?.price && (
+
+
+ €
+
+
+
Prix
+
{eventType.price}€
+
+
+ )}
+
+ {eventType?.location && (
+
+
+
+
+
+
Lieu
+
{eventType.location}
+
+
)}
- ))}
+
+
+ {/* Footer */}
+
-
- {/* Right Sidebar - Available Slots */}
-
-
-
- {selectedDate ? (
- <>
- Créneaux disponibles
-
-
- {selectedDate.toLocaleDateString("fr-FR", {
- weekday: "long",
- day: "numeric",
- month: "long",
- })}
-
- >
- ) : (
- "Sélectionnez une date"
- )}
-
+ {/* Right Panel - Calendar & Time Slots */}
+
+
+ {/* Calendar */}
+
+
+
+ {formatMonthYear(currentDate)}
+
+
+
+
+
+
- {selectedDate ? (
-
- {getAvailableSlots(selectedDate).map((slot, index) => (
-
- ))}
+ {/* Calendar Grid */}
+
+ {["Lun", "Mar", "Mer", "Jeu", "Ven", "Sam", "Dim"].map((day) => (
+
+ {day}
+
+ ))}
+
- {getAvailableSlots(selectedDate).length === 0 && (
+
+ {getDaysInMonth(currentDate).map((date, index) => (
+
+ {date ? (
+
+ ) : (
+
+ )}
+
+ ))}
+
+
+
+ {/* Time Slots */}
+
+
+ {selectedDate ? (
+ <>
+ Créneaux disponibles
+
+
+ {selectedDate.toLocaleDateString("fr-FR", {
+ weekday: "long",
+ day: "numeric",
+ month: "long",
+ })}
+
+ >
+ ) : (
+ "Sélectionnez une date"
+ )}
+
+
+ {selectedDate ? (
+
+ {getAvailableSlots(selectedDate).map((slot, index) => (
+
+ ))}
+
+ {getAvailableSlots(selectedDate).length === 0 && (
+
+
+ Aucun créneau disponible ce jour
+
+
+ )}
+
+ ) : (
-
- Aucun créneau disponible ce jour
+
+
+ Choisissez une date dans le calendrier
)}
- ) : (
-
-
-
- Choisissez une date dans le calendrier pour voir les créneaux disponibles
-
-
- )}
+
@@ -572,9 +574,9 @@ export function PublicBookingPage() {
width="md"
>
{selectedSlot && (
-
-
-
+
+
+
{selectedSlot.date.toLocaleDateString("fr-FR", {
weekday: "long",
@@ -583,8 +585,8 @@ export function PublicBookingPage() {
})}
-
-
+
+
{selectedSlot.slot.time}
diff --git a/packages/shared/src/hooks/public.ts b/packages/shared/src/hooks/public.ts
index 43c5b64..5e17b48 100644
--- a/packages/shared/src/hooks/public.ts
+++ b/packages/shared/src/hooks/public.ts
@@ -25,7 +25,7 @@ export type TimeSlot = {
export function usePublicSlots(api: AxiosInstance, shortUserId: string, standardName: string) {
return useQuery<{
- user: { name: string };
+ user: { name: string; avatar_url?: string };
eventType: EventTypeConfig;
slots: { [date: string]: TimeSlot[] };
availableSlots: TimeSlot[];