feat: update layout to fetch and provide initial movie data; enhance GlobalStoreProvider to accept initialMovies prop for improved state management
This commit is contained in:
parent
d767684c2c
commit
9051d4887c
|
|
@ -1,37 +1,29 @@
|
||||||
import "./globals.css";
|
import "./globals.css";
|
||||||
|
|
||||||
import type { Metadata } from "next";
|
|
||||||
import { Geist, Geist_Mono } from "next/font/google";
|
|
||||||
import { Navbar } from "@/components/organisms/Navbar";
|
import { Navbar } from "@/components/organisms/Navbar";
|
||||||
import { GlobalStoreProvider } from "./store/globalStore";
|
|
||||||
import { AuroraBackground } from "@/components/effects";
|
import { AuroraBackground } from "@/components/effects";
|
||||||
|
import { GlobalStoreProvider } from "./store/globalStore";
|
||||||
const geistSans = Geist({
|
import { getMovies } from "@/lib/db";
|
||||||
variable: "--font-geist-sans",
|
|
||||||
subsets: ["latin"],
|
|
||||||
});
|
|
||||||
|
|
||||||
const geistMono = Geist_Mono({
|
|
||||||
variable: "--font-geist-mono",
|
|
||||||
subsets: ["latin"],
|
|
||||||
});
|
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
|
||||||
title: "Movie List",
|
|
||||||
description: "Personal watch list and progress tracker",
|
|
||||||
};
|
|
||||||
|
|
||||||
export default async function RootLayout({
|
export default async function RootLayout({
|
||||||
children,
|
children,
|
||||||
}: Readonly<{
|
}: Readonly<{
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}>) {
|
}>) {
|
||||||
|
const movies = await getMovies();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<html lang="pl">
|
<html lang="pl">
|
||||||
<body
|
<head>
|
||||||
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
|
<title>Homepage | Movie List</title>
|
||||||
>
|
<meta
|
||||||
<GlobalStoreProvider>
|
name="description"
|
||||||
|
content="Personal watch list and progress tracker"
|
||||||
|
/>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
</head>
|
||||||
|
<body className={`antialiased`}>
|
||||||
|
<GlobalStoreProvider initialMovies={movies}>
|
||||||
<AuroraBackground />
|
<AuroraBackground />
|
||||||
<Navbar />
|
<Navbar />
|
||||||
<main className="relative">{children}</main>
|
<main className="relative">{children}</main>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
"use client";
|
"use client";
|
||||||
import { addMovieToDB, deleteMovieFromDB, updateMovieInDB } from "@/lib/db";
|
import { addMovieToDB, deleteMovieFromDB, updateMovieInDB } from "@/lib/db";
|
||||||
import { movies } from "@/lib/db/schema";
|
import { movies } from "@/lib/db/schema";
|
||||||
import { createContext, FC, use, useEffect, useState } from "react";
|
import { createContext, FC, use, useState } from "react";
|
||||||
|
|
||||||
type Movie = typeof movies.$inferSelect;
|
type Movie = typeof movies.$inferSelect;
|
||||||
|
|
||||||
|
|
@ -21,19 +21,15 @@ const globalStore = createContext<GlobalStore>({
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
|
initialMovies?: Movie[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export const GlobalStoreProvider: FC<Props> = ({ children }) => {
|
export const GlobalStoreProvider: FC<Props> = ({
|
||||||
|
children,
|
||||||
|
initialMovies = [],
|
||||||
|
}) => {
|
||||||
// Optimistic update
|
// Optimistic update
|
||||||
const [movies, setMovies] = useState<GlobalStore["movies"]>([]);
|
const [movies, setMovies] = useState<GlobalStore["movies"]>(initialMovies);
|
||||||
|
|
||||||
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;
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import { drizzle } from "drizzle-orm/libsql";
|
||||||
import { movies } from "./schema";
|
import { movies } from "./schema";
|
||||||
import { eq } from "drizzle-orm";
|
import { eq } from "drizzle-orm";
|
||||||
import { Movie } from "@/types/global";
|
import { Movie } from "@/types/global";
|
||||||
|
import { revalidatePath } from "next/cache";
|
||||||
|
|
||||||
const db = drizzle(process.env.DB_FILE_NAME!);
|
const db = drizzle(process.env.DB_FILE_NAME!);
|
||||||
|
|
||||||
|
|
@ -18,10 +19,13 @@ export const addMovieToDB = async (movie: Movie) => {
|
||||||
genre_ids: JSON.stringify(movie.genre_ids),
|
genre_ids: JSON.stringify(movie.genre_ids),
|
||||||
})
|
})
|
||||||
.onConflictDoNothing();
|
.onConflictDoNothing();
|
||||||
|
|
||||||
|
revalidatePath("/", "layout");
|
||||||
};
|
};
|
||||||
|
|
||||||
export const deleteMovieFromDB = async (id: number) => {
|
export const deleteMovieFromDB = async (id: number) => {
|
||||||
await db.delete(movies).where(eq(movies.id, id));
|
await db.delete(movies).where(eq(movies.id, id));
|
||||||
|
revalidatePath("/", "layout");
|
||||||
};
|
};
|
||||||
|
|
||||||
export const updateMovieInDB = async (
|
export const updateMovieInDB = async (
|
||||||
|
|
@ -29,4 +33,5 @@ export const updateMovieInDB = async (
|
||||||
movie: Partial<Movie>
|
movie: Partial<Movie>
|
||||||
) => {
|
) => {
|
||||||
await db.update(movies).set(movie).where(eq(movies.id, movieId));
|
await db.update(movies).set(movie).where(eq(movies.id, movieId));
|
||||||
|
revalidatePath("/", "layout");
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue