init
This commit is contained in:
135
src/app/page.tsx
Normal file
135
src/app/page.tsx
Normal file
@@ -0,0 +1,135 @@
|
||||
'use client';
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
import { createClientComponentClient } from '@supabase/auth-helpers-nextjs';
|
||||
import CameraCapture from "@/components/CameraCapture";
|
||||
import BottleGrid from "@/components/BottleGrid";
|
||||
import AuthForm from "@/components/AuthForm";
|
||||
|
||||
export default function Home() {
|
||||
const supabase = createClientComponentClient();
|
||||
const [bottles, setBottles] = useState<any[]>([]);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [user, setUser] = useState<any>(null); // Added user state
|
||||
|
||||
useEffect(() => {
|
||||
// Check session
|
||||
const checkUser = async () => {
|
||||
const { data: { session } } = await supabase.auth.getSession();
|
||||
setUser(session?.user ?? null);
|
||||
if (session?.user) {
|
||||
fetchCollection();
|
||||
} else {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
checkUser();
|
||||
|
||||
// Listen for auth changes
|
||||
const { data: { subscription } } = supabase.auth.onAuthStateChange((_event, session) => {
|
||||
setUser(session?.user ?? null);
|
||||
if (session?.user) {
|
||||
fetchCollection();
|
||||
} else {
|
||||
setBottles([]);
|
||||
}
|
||||
});
|
||||
|
||||
return () => subscription.unsubscribe();
|
||||
}, []);
|
||||
|
||||
const fetchCollection = async () => {
|
||||
setIsLoading(true);
|
||||
try {
|
||||
// Fetch bottles with their latest tasting date
|
||||
const { data, error } = await supabase
|
||||
.from('bottles')
|
||||
.select(`
|
||||
*,
|
||||
tastings (
|
||||
created_at
|
||||
)
|
||||
`)
|
||||
.order('created_at', { ascending: false });
|
||||
|
||||
if (error) throw error;
|
||||
|
||||
// Process data to get the absolute latest tasting date for each bottle
|
||||
const processedBottles = (data || []).map(bottle => {
|
||||
const lastTasted = bottle.tastings && bottle.tastings.length > 0
|
||||
? bottle.tastings.reduce((latest: string, current: any) =>
|
||||
new Date(current.created_at) > new Date(latest) ? current.created_at : latest,
|
||||
bottle.tastings[0].created_at
|
||||
)
|
||||
: null;
|
||||
|
||||
return {
|
||||
...bottle,
|
||||
last_tasted: lastTasted
|
||||
};
|
||||
});
|
||||
|
||||
setBottles(processedBottles);
|
||||
} catch (err) {
|
||||
console.error('Error fetching collection:', err);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleLogout = async () => {
|
||||
await supabase.auth.signOut();
|
||||
};
|
||||
|
||||
if (!user) {
|
||||
return (
|
||||
<main className="flex min-h-screen flex-col items-center justify-center p-6 bg-zinc-50 dark:bg-black">
|
||||
<div className="mb-12 text-center">
|
||||
<h1 className="text-5xl font-black text-zinc-900 dark:text-white tracking-tighter mb-4">
|
||||
WHISKY<span className="text-amber-600">VAULT</span>
|
||||
</h1>
|
||||
<p className="text-zinc-500 max-w-sm mx-auto">Scanne deine Flaschen, tracke deine Tastings und verwalte deinen Keller.</p>
|
||||
</div>
|
||||
<AuthForm />
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<main className="flex min-h-screen flex-col items-center gap-12 p-6 md:p-24 bg-zinc-50 dark:bg-black">
|
||||
<div className="z-10 max-w-5xl w-full flex flex-col items-center gap-8">
|
||||
<header className="w-full flex justify-between items-center">
|
||||
<h1 className="text-4xl font-black text-zinc-900 dark:text-white tracking-tighter">
|
||||
WHISKY<span className="text-amber-600">VAULT</span>
|
||||
</h1>
|
||||
<button
|
||||
onClick={handleLogout}
|
||||
className="text-sm font-medium text-zinc-500 hover:text-zinc-800 dark:hover:text-zinc-300 transition-colors"
|
||||
>
|
||||
Abmelden
|
||||
</button>
|
||||
</header>
|
||||
|
||||
<CameraCapture onSaveComplete={fetchCollection} />
|
||||
|
||||
<div className="w-full mt-12">
|
||||
<h2 className="text-2xl font-bold mb-6 text-zinc-800 dark:text-zinc-100 flex items-center gap-3">
|
||||
Deine Sammlung
|
||||
<span className="text-sm font-normal text-zinc-500 bg-zinc-100 dark:bg-zinc-800 px-3 py-1 rounded-full">
|
||||
{bottles.length}
|
||||
</span>
|
||||
</h2>
|
||||
|
||||
{isLoading ? (
|
||||
<div className="flex justify-center py-12">
|
||||
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-amber-600"></div>
|
||||
</div>
|
||||
) : (
|
||||
<BottleGrid bottles={bottles} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user