Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/hooks/useTimelineUrlState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ export interface TimelineState {
selectedDay: string; // Dynamic based on festival dates
selectedTime: TimeFilter;
selectedStages: string[];
jumpToTime?: string; // ISO format: YYYY-MM-DDTHH:mm
}

const defaultState: TimelineState = {
timelineView: "list",
selectedDay: "all",
selectedTime: "all",
selectedStages: [],
jumpToTime: undefined,
};

export function useTimelineUrlState() {
Expand All @@ -31,6 +33,7 @@ export function useTimelineUrlState() {
selectedStages:
searchParams.get("stages")?.split(",").filter(Boolean) ||
defaultState.selectedStages,
jumpToTime: searchParams.get("jumpTo") || undefined,
};
}, [searchParams]);

Expand All @@ -54,6 +57,9 @@ export function useTimelineUrlState() {
if (newState.selectedStages.length > 0) {
newParams.set("stages", newState.selectedStages.join(","));
}
if (newState.jumpToTime) {
newParams.set("jumpTo", newState.jumpToTime);
}

setSearchParams(newParams, { replace: true });
},
Expand Down
39 changes: 31 additions & 8 deletions src/pages/EditionView/tabs/ScheduleTab/TimelineControls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { TimelineNavigation } from "./TimelineNavigation";
import { useTimelineUrlState } from "@/hooks/useTimelineUrlState";
import { FilterToggle } from "@/components/filters/FilterToggle";
import { FilterContainer } from "@/components/filters/FilterContainer";
import { format } from "date-fns";

export function TimelineControls() {
const [isExpanded, setIsExpanded] = useState(false);
Expand All @@ -16,6 +17,34 @@ export function TimelineControls() {
updateState({ selectedStages: newStages });
}

function handleJumpToNow() {
const now = new Date();
const jumpToTime = format(now, "yyyy-MM-dd'T'HH:mm");
updateState({ jumpToTime });
}

function handleJumpToTime(timeOfDay: "morning" | "afternoon" | "evening") {
const now = new Date();
let targetHour = 12;

switch (timeOfDay) {
case "morning":
targetHour = 9;
break;
case "afternoon":
targetHour = 15;
break;
case "evening":
targetHour = 21;
break;
}

const targetTime = new Date(now);
targetTime.setHours(targetHour, 0, 0, 0);
const jumpToTime = format(targetTime, "yyyy-MM-dd'T'HH:mm");
updateState({ jumpToTime });
}

const activeFilterCount = selectedStages.length;
const hasActiveFilters = activeFilterCount > 0;

Expand All @@ -39,14 +68,8 @@ export function TimelineControls() {
<TimelineNavigation
selectedStages={selectedStages}
onStageToggle={handleStageToggle}
onJumpToToday={() => {
// TODO: Implement jump to today functionality
console.log("Jump to today");
}}
onJumpToTime={(timeOfDay) => {
// TODO: Implement jump to time functionality
console.log("Jump to", timeOfDay);
}}
onJumpToToday={handleJumpToNow}
onJumpToTime={handleJumpToTime}
/>
</div>
)}
Expand Down
10 changes: 5 additions & 5 deletions src/pages/EditionView/tabs/ScheduleTab/TimelineNavigation.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Button } from "@/components/ui/button";
import { Clock, Sun, Sunset, Calendar } from "lucide-react";
import { Clock, Sun, Sunset } from "lucide-react";
import { StageFilterButtons } from "./StageFilterButtons";

interface TimelineNavigationProps {
Expand All @@ -15,7 +15,7 @@ export function TimelineNavigation({
onJumpToToday,
onJumpToTime,
}: TimelineNavigationProps) {
function handleJumpToToday() {
function handleJumpToNow() {
onJumpToToday?.();
}

Expand All @@ -34,11 +34,11 @@ export function TimelineNavigation({
<Button
variant="outline"
size="sm"
onClick={handleJumpToToday}
onClick={handleJumpToNow}
className="border-purple-400 text-purple-400 hover:bg-purple-400 hover:text-white"
>
<Calendar className="h-3 w-3 mr-2" />
Jump to Today
<Clock className="h-3 w-3 mr-2" />
Jump to Now
</Button>
<Button
variant="outline"
Expand Down
16 changes: 12 additions & 4 deletions src/pages/EditionView/tabs/ScheduleTab/horizontal/Timeline.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useMemo } from "react";
import { useMemo, useCallback } from "react";
import { useScheduleData } from "@/hooks/useScheduleData";
import { calculateTimelineData } from "@/lib/timelineCalculator";
import { StageLabels } from "./StageLabels";
Expand All @@ -19,8 +19,12 @@ export function Timeline() {
editionSets,
stagesQuery.data,
);
const { state: filters } = useTimelineUrlState();
const { selectedDay, selectedTime, selectedStages } = filters;
const { state: filters, updateState } = useTimelineUrlState();
const { selectedDay, selectedTime, selectedStages, jumpToTime } = filters;

const handleScrollComplete = useCallback(() => {
updateState({ jumpToTime: undefined });
}, [updateState]);

const timelineData = useMemo(() => {
if (!edition || !edition.start_date || !edition.end_date) {
Expand Down Expand Up @@ -122,7 +126,11 @@ export function Timeline() {
<div className="space-y-8">
<div className="relative bg-white/5 rounded-lg p-4">
<StageLabels stages={timelineData.stages} />
<TimelineContainer timelineData={timelineData} />
<TimelineContainer
timelineData={timelineData}
jumpToTime={jumpToTime}
onScrollComplete={handleScrollComplete}
/>
</div>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,41 @@
import { useRef } from "react";
import { useRef, useEffect } from "react";
import { TimeScale } from "./TimeScale";
import { StageRow } from "./StageRow";
import type { TimelineData } from "@/lib/timelineCalculator";
import { differenceInMinutes } from "date-fns";

interface TimelineContainerProps {
timelineData: TimelineData;
jumpToTime?: string;
onScrollComplete?: () => void;
}

export function TimelineContainer({ timelineData }: TimelineContainerProps) {
export function TimelineContainer({
timelineData,
jumpToTime,
onScrollComplete,
}: TimelineContainerProps) {
const scrollContainerRef = useRef<HTMLDivElement>(null);

useEffect(() => {
if (!jumpToTime || !scrollContainerRef.current) return;

const targetTime = new Date(jumpToTime);
const { festivalStart } = timelineData;

const minutesFromStart = differenceInMinutes(targetTime, festivalStart);
const scrollPosition = minutesFromStart * 2;

scrollContainerRef.current.scrollTo({
left: scrollPosition,
behavior: "smooth",
});

if (onScrollComplete) {
setTimeout(onScrollComplete, 500);
}
}, [jumpToTime, timelineData, onScrollComplete]);

return (
<div
ref={scrollContainerRef}
Expand Down
Loading