moviebox/src/app/store/globalStore.tsx

69 lines
1.6 KiB
TypeScript

"use client";
import { addMovieToDB, deleteMovieFromDB, updateMovieInDB } from "@/lib/db";
import { movies } from "@/lib/db/schema";
import { createContext, FC, use, useEffect, useState } from "react";
type Movie = typeof movies.$inferSelect;
type GlobalStore = {
movies: Movie[];
addMovie: (movie: Movie) => void;
deleteMovie: (id: number) => void;
updateMovie: (id: number, movie: Partial<Movie>) => void;
};
const globalStore = createContext<GlobalStore>({
movies: [],
addMovie: () => {},
deleteMovie: () => {},
updateMovie: () => {},
});
type Props = {
children: React.ReactNode;
};
export const GlobalStoreProvider: FC<Props> = ({ children }) => {
// 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) => {
if (movies.find((m) => m.id === movie.id)) return;
addMovieToDB(movie);
setMovies((prev) => [...prev, movie]);
};
const deleteMovie = async (id: number) => {
deleteMovieFromDB(id);
setMovies((prev) => prev.filter((m) => m.id !== id));
};
const updateMovie = async (id: number, movie: Partial<Movie>) => {
updateMovieInDB(id, movie);
setMovies((prev) =>
prev.map((m) => (m.id === id ? { ...m, ...movie } : m))
);
};
return (
<globalStore.Provider
value={{ movies, addMovie, deleteMovie, updateMovie }}
>
{children}
</globalStore.Provider>
);
};
export const useGlobalStore = () => {
return use(globalStore);
};