diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 97d9036..361c3f0 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -2,6 +2,8 @@ import type { Metadata } from "next"; import { Geist, Geist_Mono } from "next/font/google"; import "./globals.css"; import { Navbar } from "@/components/organisms/Navbar"; +import { GlobalStoreProvider } from "./store/globalStore"; +import { getMovies } from "@/lib/db"; const geistSans = Geist({ variable: "--font-geist-sans", @@ -18,19 +20,23 @@ export const metadata: Metadata = { description: "Generated by create next app", }; -export default function RootLayout({ +export default async function RootLayout({ children, }: Readonly<{ children: React.ReactNode; }>) { + const movies = await getMovies(); + return ( - + + - {children} + {children} + ); diff --git a/src/app/store/globalStore.tsx b/src/app/store/globalStore.tsx new file mode 100644 index 0000000..476476a --- /dev/null +++ b/src/app/store/globalStore.tsx @@ -0,0 +1,44 @@ +"use client"; +import { movies } from "@/lib/db/schema"; +import { createContext, FC, use, useState } from "react"; + +type GlobalStore = { + movies: (typeof movies.$inferSelect)[]; + addMovie: (movie: typeof movies.$inferSelect) => void; + deleteMovie: (id: number) => void; +}; + +const globalStore = createContext({ + movies: [], + addMovie: () => {}, + deleteMovie: () => {}, +}); + +type Props = { + children: React.ReactNode; + initialMovies: GlobalStore["movies"]; +}; + +export const GlobalStoreProvider: FC = ({ children, initialMovies }) => { + const [movies, setMovies] = useState(initialMovies); + + const addMovie = async (movie: GlobalStore["movies"][number]) => { + if (movies.find((m) => m.id === movie.id)) return; + + setMovies((prev) => [...prev, movie]); + }; + + const deleteMovie = async (id: number) => { + setMovies((prev) => prev.filter((m) => m.id !== id)); + }; + + return ( + + {children} + + ); +}; + +export const useGlobalStore = () => { + return use(globalStore); +}; diff --git a/src/lib/db/index.ts b/src/lib/db/index.ts index 24b14f9..e03433b 100644 --- a/src/lib/db/index.ts +++ b/src/lib/db/index.ts @@ -1,3 +1,18 @@ +"use server"; import { drizzle } from "drizzle-orm/libsql"; +import { movies } from "./schema"; +import { eq } from "drizzle-orm"; -export const db = drizzle(process.env.DB_FILE_NAME!); +const db = drizzle(process.env.DB_FILE_NAME!); + +export const getMovies = async () => { + return await db.select().from(movies); +}; + +export const addMovie = async (movie: typeof movies.$inferInsert) => { + await db.insert(movies).values(movie).onConflictDoNothing(); +}; + +export const deleteMovie = async (id: number) => { + await db.delete(movies).where(eq(movies.id, id)); +}; diff --git a/src/lib/db/schema.ts b/src/lib/db/schema.ts index 9081e23..756618b 100644 --- a/src/lib/db/schema.ts +++ b/src/lib/db/schema.ts @@ -1,10 +1,13 @@ -import { integer, sqliteTable, text } from "drizzle-orm/sqlite-core"; +import { integer, real, sqliteTable, text } from "drizzle-orm/sqlite-core"; export const movies = sqliteTable("movies", { id: integer("id").primaryKey(), title: text("title").notNull(), - releaseDate: text("release_date"), - posterPath: text("poster_path"), - status: text("status"), // to-watch, seen - notes: text("notes"), + overview: text("overview").notNull(), + popularity: real("popularity").notNull(), + releaseDate: text("release_date").notNull(), + posterPath: text("poster_path").notNull(), + seen: integer("seen").default(0).notNull(), + favorite: integer("favorite").default(0).notNull(), + notes: text("notes").default("").notNull(), });