Refactor layout and add new pages for movie browsing and searching: update RootLayout to include GlobalStoreProvider and Navbar, create new Home, Odkrywaj, and Search pages with movie listings and API integration for enhanced user experience.

This commit is contained in:
Norbert Maciaszek 2025-08-16 13:42:42 +02:00
parent 7ecbc55843
commit f88b7ede7d
7 changed files with 38 additions and 25 deletions

View File

@ -1,19 +0,0 @@
import { getMovies } from "@/lib/db";
import { GlobalStoreProvider } from "../store/globalStore";
import { Navbar } from "@/components/organisms/Navbar";
export const revalidate = 0;
export default async function WithGlobalDataLayout({
children,
}: {
children: React.ReactNode;
}) {
const movies = await getMovies();
return (
<GlobalStoreProvider initialMovies={movies}>
<Navbar />
<main className="[&>:last-child]:mb-0">{children}</main>
</GlobalStoreProvider>
);
}

View File

@ -0,0 +1,14 @@
import { getMovies } from "@/lib/db";
import { NextResponse } from "next/server";
export const GET = async () => {
const movies = await getMovies();
const res = NextResponse.json(movies);
res.headers.set(
"Cache-Control",
"public, max-age=3, stale-while-revalidate=30"
);
return res;
};

View File

@ -2,6 +2,8 @@ import "./globals.css";
import type { Metadata } from "next"; import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google"; import { Geist, Geist_Mono } from "next/font/google";
import { Navbar } from "@/components/organisms/Navbar";
import { GlobalStoreProvider } from "./store/globalStore";
const geistSans = Geist({ const geistSans = Geist({
variable: "--font-geist-sans", variable: "--font-geist-sans",
@ -24,11 +26,14 @@ export default async function RootLayout({
children: React.ReactNode; children: React.ReactNode;
}>) { }>) {
return ( return (
<html lang="en"> <html lang="pl">
<body <body
className={`${geistSans.variable} ${geistMono.variable} antialiased`} className={`${geistSans.variable} ${geistMono.variable} antialiased`}
> >
{children} <GlobalStoreProvider>
<Navbar />
<main className="[&>:last-child]:mb-0">{children}</main>
</GlobalStoreProvider>
</body> </body>
</html> </html>
); );

View File

@ -12,6 +12,7 @@ import { MovieCard } from "@/components/atoms/MovieCard";
export const revalidate = 43200; export const revalidate = 43200;
export default async function Home() { export default async function Home() {
const lastModified = new Date().toISOString();
const [nowPlayingData, popularData, trendingData, upcomingData] = const [nowPlayingData, popularData, trendingData, upcomingData] =
await Promise.all([ await Promise.all([
getNowPlayingMovies(), getNowPlayingMovies(),
@ -80,6 +81,10 @@ export default async function Home() {
</Carousel> </Carousel>
</section> </section>
</div> </div>
<div className="p-2 text-center text-xs text-gray-500">
<p>Ostatnia aktualizacja: {lastModified}</p>
</div>
</> </>
); );
} }

View File

@ -1,6 +1,6 @@
"use client"; "use client";
import { movies } from "@/lib/db/schema"; import { movies } from "@/lib/db/schema";
import { createContext, FC, use, useState } from "react"; import { createContext, FC, use, useEffect, useState } from "react";
type Movie = typeof movies.$inferSelect; type Movie = typeof movies.$inferSelect;
@ -20,11 +20,19 @@ const globalStore = createContext<GlobalStore>({
type Props = { type Props = {
children: React.ReactNode; children: React.ReactNode;
initialMovies: Movie[];
}; };
export const GlobalStoreProvider: FC<Props> = ({ children, initialMovies }) => { export const GlobalStoreProvider: FC<Props> = ({ children }) => {
const [movies, setMovies] = useState<GlobalStore["movies"]>(initialMovies); // Optimistic update
const [movies, setMovies] = useState<GlobalStore["movies"]>([]);
useEffect(() => {
fetch("/api/movies")
.then((res) => res.json())
.then((data) => {
setMovies(data);
});
}, []);
const addMovie = async (movie: Movie) => { const addMovie = async (movie: Movie) => {
if (movies.find((m) => m.id === movie.id)) return; if (movies.find((m) => m.id === movie.id)) return;