diff --git a/public/Logo.png b/public/Logo.png index c64b0bb..f45b7ad 100644 Binary files a/public/Logo.png and b/public/Logo.png differ diff --git a/public/LogoFull.png b/public/LogoFull.png new file mode 100644 index 0000000..c64b0bb Binary files /dev/null and b/public/LogoFull.png differ diff --git a/public/icon.png b/public/icon.png new file mode 100644 index 0000000..1ffa902 Binary files /dev/null and b/public/icon.png differ diff --git a/src/components/app/Main.tsx b/src/components/app/Main.tsx index 9649bbe..68d36b0 100644 --- a/src/components/app/Main.tsx +++ b/src/components/app/Main.tsx @@ -4,12 +4,22 @@ import { LogOut, Menu } from 'lucide-react'; import { useAuth } from '@/contexts/AuthContext'; import { useNavigate } from 'react-router-dom'; import DashboardContainer from '../dashboard/DashboardContainer'; -import { cn } from '@/lib/utils'; -const Main: React.FC = () => { +import { DropdownMenu, DropdownMenuContent, DropdownMenuTrigger } from '@/components/ui/dropdown-menu'; +import { HeaderProvider, useHeader } from '@/contexts/HeaderContext'; + +const MainShell: React.FC = () => { + const { header, resetHeader } = useHeader(); + + useEffect(() => { + return () => { + resetHeader(); + }; + }, [resetHeader]); + const { user, logout } = useAuth(); const navigate = useNavigate(); const [hasActiveEvent, setHasActiveEvent] = useState(false); - const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false); + // header is already available above // Check for active events - This will be replaced with actual API call useEffect(() => { @@ -54,26 +64,45 @@ const Main: React.FC = () => {
- -
navigate('/')} > - Logo + {!header.left && ( + Logo + )}
+ + {header.mobileMenu ? ( + + + + + {header.mobileMenu} + + ) : null} + + {header.left ? ( +
{header.left}
+ ) : null}
+ + {header.title && ( +
+ {header.title} +
+ )}
@@ -105,4 +134,12 @@ const Main: React.FC = () => { ); }; +const Main: React.FC = () => { + return ( + + + + ); +}; + export default Main; \ No newline at end of file diff --git a/src/contexts/HeaderContext.tsx b/src/contexts/HeaderContext.tsx new file mode 100644 index 0000000..1279e1a --- /dev/null +++ b/src/contexts/HeaderContext.tsx @@ -0,0 +1,43 @@ +import React, { createContext, useCallback, useContext, useMemo, useState } from 'react'; + +type HeaderState = { + title: string | null; + left: React.ReactNode | null; + mobileMenu: React.ReactNode | null; +}; + +type HeaderContextValue = { + header: HeaderState; + setHeader: (next: Partial) => void; + resetHeader: () => void; +}; + +const DEFAULT_HEADER: HeaderState = { + title: null, + left: null, + mobileMenu: null, +}; + +const HeaderContext = createContext(null); + +export const HeaderProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { + const [header, setHeaderState] = useState(DEFAULT_HEADER); + + const setHeader = useCallback((next: Partial) => { + setHeaderState((prev) => ({ ...prev, ...next })); + }, []); + + const resetHeader = useCallback(() => { + setHeaderState(DEFAULT_HEADER); + }, []); + + const value = useMemo(() => ({ header, setHeader, resetHeader }), [header, setHeader, resetHeader]); + + return {children}; +}; + +export const useHeader = () => { + const ctx = useContext(HeaderContext); + if (!ctx) throw new Error('useHeader must be used within HeaderProvider'); + return ctx; +}; diff --git a/src/features/event/components/EventFormInline.tsx b/src/features/event/components/EventFormInline.tsx index 266684a..2000e13 100644 --- a/src/features/event/components/EventFormInline.tsx +++ b/src/features/event/components/EventFormInline.tsx @@ -564,9 +564,6 @@ const EventFormInline: React.FC = ({ onSuccess, onCancel, {isMobile ? (
-
- {mode === 'edit' ? 'Event bearbeiten' : 'Event erstellen'} -
{loadingInitial ? 'Lade…' : ''}
{error &&
{error}
} diff --git a/src/features/event/components/EventWizard.tsx b/src/features/event/components/EventWizard.tsx index a1f5852..516c9a0 100644 --- a/src/features/event/components/EventWizard.tsx +++ b/src/features/event/components/EventWizard.tsx @@ -1,25 +1,80 @@ import React, { useEffect, useMemo, useRef, useState } from 'react'; -import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { Card, CardContent } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; +import { DropdownMenuItem } from '@/components/ui/dropdown-menu'; import { type Event } from '@/features/event/api/eventService'; +import { ArrowLeft, LayoutGrid } from 'lucide-react'; +import { useHeader } from '@/contexts/HeaderContext'; import EventFormInline from './EventFormInline'; interface EventWizardProps { onComplete: () => void; + onBackToOverview: () => void; events: Event[]; loading: boolean; error: string | null; onReload: () => void; } -const EventWizard: React.FC = ({ onComplete, events, loading, error, onReload }) => { +const EventWizard: React.FC = ({ onComplete, onBackToOverview, events, loading, error, onReload }) => { const [showForm, setShowForm] = useState(false); const [activeEventId, setActiveEventId] = useState(null); + const { setHeader, resetHeader } = useHeader(); + + const canGoTimeline = showForm; + const handleBackToTimeline = () => { + setShowForm(false); + setActiveEventId(null); + }; useEffect(() => { onReload(); }, [onReload]); + useEffect(() => { + const title = showForm ? (activeEventId ? 'Event bearbeiten' : 'Event erstellen') : 'Veranstaltungen'; + + setHeader({ + title, + left: ( + <> + + {showForm && ( + + )} + + ), + mobileMenu: ( + <> + + + Zurück zur Übersicht + + {showForm && ( + + + Zurück zur Timeline + + )} + + ), + }); + + return () => { + resetHeader(); + }; + }, [activeEventId, onBackToOverview, resetHeader, setHeader, showForm]); + const sortedEvents = useMemo(() => { if (!events.length) return [] as Event[]; return [...events].sort((a, b) => { @@ -71,23 +126,9 @@ const EventWizard: React.FC = ({ onComplete, events, loading, return ( - - Veranstaltungen - {showForm ? (
-
- -
void; + onBackToOverview: () => void; } -const EventWizardContainer: React.FC = ({ onComplete }) => { +const EventWizardContainer: React.FC = ({ onComplete, onBackToOverview }) => { const apiFetch = useApiFetch(); const [events, setEvents] = useState([]); const [loading, setLoading] = useState(false); @@ -32,6 +33,7 @@ const EventWizardContainer: React.FC = ({ onComplete return ( { const { Wrapper } = renderWithProviders(
); render( - {}} />, + {}} onBackToOverview={() => {}} />, { wrapper: Wrapper as any } ); @@ -61,7 +61,7 @@ describe('EventWizardContainer (integration)', () => { const { Wrapper } = renderWithProviders(
); render( - {}} />, + {}} onBackToOverview={() => {}} />, { wrapper: Wrapper as any } ); diff --git a/src/features/event/dashboardModule.tsx b/src/features/event/dashboardModule.tsx index 1263ff5..95a3bcf 100644 --- a/src/features/event/dashboardModule.tsx +++ b/src/features/event/dashboardModule.tsx @@ -1,6 +1,4 @@ import React from 'react'; -import { ArrowLeft } from 'lucide-react'; -import { Button } from '@/components/ui/button'; import EventWizardContainer from '@/features/event/containers/EventWizardContainer'; import { type DashboardModule } from '@/components/dashboard/dashboardModuleTypes'; @@ -10,16 +8,6 @@ export const eventDashboardModule: DashboardModule = { getDescription: () => 'Verwalte deine Veranstaltungen', getIllustration: () => '/images/robo/robo_event.png', renderWizard: (_ctx, onBack) => ( -
- - -
+ ), };