feat: integrate Zustand for global state management;

This commit is contained in:
Norbert Maciaszek
2025-11-09 11:10:27 +01:00
parent d6ca9e1429
commit fede32d150
17 changed files with 333 additions and 335 deletions

View File

@@ -1,11 +1,11 @@
'use client';
import { FC } from 'react';
import { useGlobalStore } from '@/app/store/globalStore';
import { FaFire, FaPlusCircle, FaTrash } from 'react-icons/fa';
import Link from 'next/link';
import { RxEyeOpen } from 'react-icons/rx';
import { MdFavorite } from 'react-icons/md';
import { RiCalendarCheckLine, RiCalendarScheduleLine } from 'react-icons/ri';
import { useGlobalStore } from '@/app/store/global';
type Props = Movie & {
showDayCounter?: boolean;
@@ -17,16 +17,14 @@ export const MovieCard: FC<Props> = ({
simpleToggle = false,
...movie
}) => {
const {
movies,
addMovie: addMovieToStore,
deleteMovie: deleteMovieFromStore,
updateMovie: updateMovieInStore,
} = useGlobalStore();
const movies = useGlobalStore(state => state.movies);
const addMovie = useGlobalStore(state => state.addMovie);
const deleteMovie = useGlobalStore(state => state.deleteMovie);
const updateMovie = useGlobalStore(state => state.updateMovie);
const { vote_average, popularity, poster_path, title, overview } = movie;
const { id } = movie;
const alreadyInStore = movies.find(m => m.id === id);
const alreadyInStore = movies.find(m => m.id == id);
const seen = alreadyInStore?.seen || movie.seen;
const favorite = alreadyInStore?.favorite || movie.favorite;
@@ -40,22 +38,22 @@ export const MovieCard: FC<Props> = ({
: 'from-red-400 to-pink-400';
const handleAdd = () => {
addMovieToStore(movie);
addMovie(movie);
};
const handleRemove = () => {
deleteMovieFromStore(id);
deleteMovie(id);
};
const handleSeen = () => {
updateMovieInStore(id, {
updateMovie(id, {
seen: !movie.seen,
favorite: false,
});
};
const handleFavorite = () => {
updateMovieInStore(id, {
updateMovie(id, {
favorite: !movie.favorite,
seen: movie.seen || !movie.favorite,
});

View File

@@ -3,8 +3,7 @@ import { formatter } from '@/helpers/formater';
import Link from 'next/link';
import { FC } from 'react';
import { FaCalendar, FaClock, FaStar, FaEye, FaHeart } from 'react-icons/fa';
import { motion, useAnimationControls, useMotionValue } from 'framer-motion';
import { useGlobalStore } from '@/app/store/globalStore';
import { useGlobalStore } from '@/app/store/global';
type Props = {
movie: Movie;
@@ -17,10 +16,7 @@ export const MovieRow: FC<Props> = ({
isUpcoming = false,
compact = false,
}) => {
const { movies, addMovie, updateMovie } = useGlobalStore();
const dragControls = useAnimationControls();
const x = useMotionValue(0);
const movies = useGlobalStore(state => state.movies);
const daysSinceRelease = Math.abs(
Math.floor(
@@ -30,128 +26,77 @@ export const MovieRow: FC<Props> = ({
);
// Check if movie is already in store.
const movieInStore = movies.find(m => m.id === movie.id);
const movieInStore = movies.find(m => m.id == movie.id);
const isWatched = movieInStore?.seen || false;
const isFavorite = movieInStore?.favorite || false;
const handleMarkAsWatched = () => {
if (movieInStore) {
updateMovie(movie.id, { seen: !isWatched });
} else {
addMovie({ ...movie, seen: true, favorite: false });
}
};
const handleAddToFavorites = () => {
if (movieInStore) {
updateMovie(movie.id, { favorite: !isFavorite, seen: true });
} else {
addMovie({ ...movie, seen: true, favorite: true });
}
};
const handleDragAction = () => {
const threshold = 70;
if (x.get() > threshold) {
handleAddToFavorites();
} else if (x.get() < -threshold) {
handleMarkAsWatched();
}
dragControls.start({
x: 0,
});
};
return (
<div className="relative overflow-hidden rounded-xl">
{/* Background actions */}
<div className="absolute inset-0 flex">
<div className="absolute right-0 h-full w-24 bg-green-500/20 flex items-center justify-center cursor-pointer">
<FaEye className="w-5 h-5 transition-colors text-green-500" />
</div>
<div className="absolute left-0 h-full w-24 bg-red-500/20 flex items-center justify-center cursor-pointer">
<FaHeart className="w-5 h-5 transition-colors text-red-500" />
</div>
</div>
<motion.div
drag="x"
style={{ x }}
animate={dragControls}
dragConstraints={{ left: -80, right: 80 }}
dragElastic={0.01}
dragMomentum={false}
whileDrag={{ cursor: 'grabbing' }}
onDragEnd={handleDragAction}
className="relative z-10"
<Link
href={`/film/${movie.id}`}
draggable={false}
className="flex items-center gap-4 p-3 rounded-lg bg-gray-800 hover:bg-gray-800 transition-colors group"
>
<Link
href={`/film/${movie.id}`}
draggable={false}
className="flex items-center gap-4 p-3 rounded-lg bg-gray-800 hover:bg-gray-800 transition-colors group"
>
<div className="relative w-12 h-16 rounded overflow-hidden flex-shrink-0">
<img
src={`https://image.tmdb.org/t/p/w154${movie.poster_path}`}
alt={movie.title}
className="object-cover inset-0"
sizes="48px"
/>
</div>
<div className="relative w-12 h-16 rounded overflow-hidden flex-shrink-0">
<img
src={`https://image.tmdb.org/t/p/w154${movie.poster_path}`}
alt={movie.title}
className="object-cover inset-0"
sizes="48px"
/>
</div>
<div className="flex-1 min-w-0">
<h3 className="text-white font-medium text-sm truncate group-hover:text-blue-400 transition-colors">
{movie.title}
</h3>
<div className="flex items-center gap-3 mt-1">
<div className="flex items-center gap-1 text-gray-400 text-xs">
{isUpcoming ? (
<FaCalendar className="w-3 h-3" />
) : (
<FaClock className="w-3 h-3" />
)}
<span>{formatter.formatDate(movie.release_date)}</span>
<div className="flex-1 min-w-0">
<h3 className="text-white font-medium text-sm truncate group-hover:text-blue-400 transition-colors">
{movie.title}
</h3>
<div className="flex items-center gap-3 mt-1">
<div className="flex items-center gap-1 text-gray-400 text-xs">
{isUpcoming ? (
<FaCalendar className="w-3 h-3" />
) : (
<FaClock className="w-3 h-3" />
)}
<span>{formatter.formatDate(movie.release_date)}</span>
</div>
{!!movie.vote_average && (
<div className="flex items-center gap-1 text-yellow-400 text-xs">
<FaStar className="w-3 h-3 fill-current" />
<span>{movie.vote_average.toFixed(1)}</span>
</div>
)}
{!!movie.vote_average && (
<div className="flex items-center gap-1 text-yellow-400 text-xs">
<FaStar className="w-3 h-3 fill-current" />
<span>{movie.vote_average.toFixed(1)}</span>
</div>
)}
{(isFavorite || movie.favorite) && (
<div
className="w-2 h-2 bg-red-500 rounded-full"
title="Ulubione"
/>
)}
{(isFavorite || movie.favorite) && (
<div
className="w-2 h-2 bg-red-500 rounded-full"
title="Ulubione"
/>
)}
{(isWatched || movie.seen) && (
<div
className="w-2 h-2 bg-green-500 rounded-full"
title="Obejrzane"
/>
)}
</div>
{(isWatched || movie.seen) && (
<div
className="w-2 h-2 bg-green-500 rounded-full"
title="Obejrzane"
/>
)}
</div>
</div>
{!compact && (
<div
className={`text-xs px-2 py-1 rounded-full font-medium ${
isUpcoming
? 'bg-blue-500/20 text-blue-400'
: 'bg-green-500/20 text-green-400'
}`}
>
{isUpcoming
? `za ${daysSinceRelease} dni`
: `od ${daysSinceRelease} dni`}
</div>
)}
</Link>
</motion.div>
{!compact && (
<div
className={`text-xs px-2 py-1 rounded-full font-medium ${
isUpcoming
? 'bg-blue-500/20 text-blue-400'
: 'bg-green-500/20 text-green-400'
}`}
>
{isUpcoming
? `za ${daysSinceRelease} dni`
: `od ${daysSinceRelease} dni`}
</div>
)}
</Link>
</div>
);
};

View File

@@ -1,9 +1,9 @@
"use client";
'use client';
import { BackButton } from "@/components/atoms/BackButton";
import { formatter } from "@/helpers/formater";
import { PersonDetailsRich } from "@/lib/tmdb/types";
import { FC } from "react";
import { BackButton } from '@/components/atoms/BackButton';
import { formatter } from '@/helpers/formater';
import { PersonDetailsRich } from '@/lib/tmdb/types';
import { FC } from 'react';
import {
FaCalendarAlt,
FaMapMarkerAlt,
@@ -15,7 +15,7 @@ import {
FaTwitter,
FaYoutube,
FaTiktok,
} from "react-icons/fa";
} from 'react-icons/fa';
type Props = {
personDetails: PersonDetailsRich;
@@ -37,13 +37,13 @@ export const ActorHero: FC<Props> = ({ personDetails }) => {
const getGenderText = (gender: number) => {
switch (gender) {
case 1:
return "Kobieta";
return 'Kobieta';
case 2:
return "Mężczyzna";
return 'Mężczyzna';
case 3:
return "Niebinarne";
return 'Niebinarne';
default:
return "Nie określono";
return 'Nie określono';
}
};
@@ -65,7 +65,7 @@ export const ActorHero: FC<Props> = ({ personDetails }) => {
src={
personDetails.profile_path
? `https://image.tmdb.org/t/p/w500${personDetails.profile_path}`
: "/api/placeholder/400/600"
: '/api/placeholder/400/600'
}
alt={personDetails.name}
className="w-80 h-auto rounded-2xl shadow-2xl shadow-purple-500/20 group-hover:shadow-purple-500/40 transition-all duration-500"
@@ -88,9 +88,9 @@ export const ActorHero: FC<Props> = ({ personDetails }) => {
{calculateAge(
personDetails.birthday,
personDetails.deathday
)}{" "}
)}{' '}
lat
{personDetails.deathday && " w chwili śmierci"})
{personDetails.deathday && ' w chwili śmierci'})
</span>
)}
@@ -114,8 +114,8 @@ export const ActorHero: FC<Props> = ({ personDetails }) => {
{personDetails.also_known_as.length > 0 && (
<div className="mb-4">
<p className="text-gray-400 text-sm">
Znany również jako:{" "}
{personDetails.also_known_as.slice(0, 3).join(", ")}
Znany również jako:{' '}
{personDetails.also_known_as.slice(0, 3).join(', ')}
</p>
</div>
)}
@@ -171,7 +171,7 @@ export const ActorHero: FC<Props> = ({ personDetails }) => {
</h3>
<div className="text-gray-300 leading-relaxed text-lg space-y-4">
{personDetails.biography
.split("\n\n")
.split('\n\n')
.map((paragraph, index) => (
<p key={index}>{paragraph}</p>
))}
@@ -185,7 +185,7 @@ export const ActorHero: FC<Props> = ({ personDetails }) => {
<h3 className="text-lg font-semibold mb-3 text-purple-300">
Linki
</h3>
<div className="flex gap-4">
<div className="flex flex-wrap gap-4">
{Object.entries(personDetails.external_ids).map(
([key, value]) => {
if (!(key in externalIdsMap) || !value) {
@@ -222,32 +222,32 @@ export const ActorHero: FC<Props> = ({ personDetails }) => {
const externalIdsMap = {
facebook_id: {
label: "Facebook",
label: 'Facebook',
icon: <FaFacebook />,
url: (id: string) => `https://www.facebook.com/${id}`,
},
instagram_id: {
label: "Instagram",
label: 'Instagram',
icon: <FaInstagram />,
url: (id: string) => `https://www.instagram.com/${id}`,
},
twitter_id: {
label: "Twitter",
label: 'Twitter',
icon: <FaTwitter />,
url: (id: string) => `https://www.twitter.com/${id}`,
},
tiktok_id: {
label: "TikTok",
label: 'TikTok',
icon: <FaTiktok />,
url: (id: string) => `https://www.tiktok.com/${id}`,
},
youtube_id: {
label: "YouTube",
label: 'YouTube',
icon: <FaYoutube />,
url: (id: string) => `https://www.youtube.com/${id}`,
},
imdb_id: {
label: "IMDb",
label: 'IMDb',
icon: <FaImdb />,
url: (id: string) => `https://www.imdb.com/name/${id}`,
},

View File

@@ -1,10 +1,9 @@
"use client";
import { BackButton } from "@/components/atoms/BackButton";
import { Button } from "@/components/atoms/Button";
import { GenreLabel } from "@/components/atoms/GenreLabel";
import { MovieDetailsRich } from "@/lib/tmdb/types";
import { useGlobalStore } from "@/app/store/globalStore";
import { FC } from "react";
'use client';
import { BackButton } from '@/components/atoms/BackButton';
import { Button } from '@/components/atoms/Button';
import { GenreLabel } from '@/components/atoms/GenreLabel';
import { MovieDetailsRich } from '@/lib/tmdb/types';
import { FC } from 'react';
import {
FaHeart,
FaBookmark,
@@ -12,19 +11,23 @@ import {
FaCalendar,
FaGlobe,
FaEye,
} from "react-icons/fa";
import { convertToMovie } from "@/helpers/convertToMovie";
import { formatter } from "@/helpers/formater";
} from 'react-icons/fa';
import { convertToMovie } from '@/helpers/convertToMovie';
import { formatter } from '@/helpers/formater';
import { useGlobalStore } from '@/app/store/global';
type Props = {
movieDetails: MovieDetailsRich;
};
export const HeroMovie: FC<Props> = ({ movieDetails }) => {
const { movies, addMovie, deleteMovie, updateMovie } = useGlobalStore();
const movies = useGlobalStore(state => state.movies);
const addMovie = useGlobalStore(state => state.addMovie);
const deleteMovie = useGlobalStore(state => state.deleteMovie);
const updateMovie = useGlobalStore(state => state.updateMovie);
// Check if movie is in store and get its state.
const movieInStore = movies.find((m) => m.id === movieDetails.id);
const movieInStore = movies.find(m => m.id == movieDetails.id);
const isInStore = !!movieInStore;
const isFavorite = movieInStore?.favorite || false;
const isSeen = movieInStore?.seen || false;
@@ -115,8 +118,8 @@ export const HeroMovie: FC<Props> = ({ movieDetails }) => {
key={i}
className={`text-2xl ${
i < Math.round(movieDetails.vote_average / 2)
? "text-yellow-400"
: "text-gray-600"
? 'text-yellow-400'
: 'text-gray-600'
}`}
>
@@ -173,7 +176,7 @@ export const HeroMovie: FC<Props> = ({ movieDetails }) => {
Gatunki
</h3>
<div className="flex flex-wrap gap-2">
{movieDetails.genres.map((genre) => (
{movieDetails.genres.map(genre => (
<GenreLabel
key={genre.id}
genre={genre.name}
@@ -203,47 +206,47 @@ export const HeroMovie: FC<Props> = ({ movieDetails }) => {
gradient={
isInStore
? {
from: "from-purple-600 hover:from-purple-500",
to: "to-emerald-600 hover:to-emerald-500",
from: 'from-purple-600 hover:from-purple-500',
to: 'to-emerald-600 hover:to-emerald-500',
}
: {
from: "from-purple-600 hover:from-purple-500",
to: "to-pink-600 hover:to-pink-500",
from: 'from-purple-600 hover:from-purple-500',
to: 'to-pink-600 hover:to-pink-500',
}
}
className={`flex items-center gap-3`}
onClick={handleAddToList}
>
<FaBookmark />
{isInStore ? "Usuń z listy" : "Dodaj do listy"}
{isInStore ? 'Usuń z listy' : 'Dodaj do listy'}
</Button>
<Button
theme={isFavorite ? "rosePink" : "glass"}
theme={isFavorite ? 'rosePink' : 'glass'}
className={`flex items-center gap-3 ${
isFavorite
? "bg-gradient-to-r border-rose-400/30"
: ""
? 'bg-gradient-to-r border-rose-400/30'
: ''
}`}
onClick={handleToggleFavorite}
>
<FaHeart
className={isFavorite ? "text-rose-200" : ""}
className={isFavorite ? 'text-rose-200' : ''}
/>
{isFavorite
? "Usuń z ulubionych"
: "Dodaj do ulubionych"}
? 'Usuń z ulubionych'
: 'Dodaj do ulubionych'}
</Button>
<Button
theme={isSeen ? "emeraldTeal" : "glass"}
theme={isSeen ? 'emeraldTeal' : 'glass'}
className={`flex items-center gap-3 ${
isSeen ? "bg-gradient-to-r border-emerald-400/30" : ""
isSeen ? 'bg-gradient-to-r border-emerald-400/30' : ''
}`}
onClick={handleToggleSeen}
>
<FaEye className={isSeen ? "text-emerald-200" : ""} />
<FaEye className={isSeen ? 'text-emerald-200' : ''} />
{isSeen
? "Oznacz jako nieobejrzany"
: "Oznacz jako obejrzany"}
? 'Oznacz jako nieobejrzany'
: 'Oznacz jako obejrzany'}
</Button>
</div>
)}

View File

@@ -1,10 +1,10 @@
"use client";
import Link from "next/link";
import { Button } from "@/components/atoms/Button";
import { MovieDetailsRich } from "@/lib/tmdb/types";
import { FC, useState } from "react";
import { FaDollarSign } from "react-icons/fa";
import { formatter } from "@/helpers/formater";
'use client';
import Link from 'next/link';
import { Button } from '@/components/atoms/Button';
import { MovieDetailsRich } from '@/lib/tmdb/types';
import { FC, useState } from 'react';
import { FaDollarSign } from 'react-icons/fa';
import { formatter } from '@/helpers/formater';
type Props = {
movieDetails: MovieDetailsRich;
@@ -13,16 +13,10 @@ type Props = {
export const MovieCast: FC<Props> = ({ movieDetails }) => {
const [limit, setLimit] = useState(8);
const director = movieDetails?.credits.crew.find(
(member) => member.job === "Director"
member => member.job === 'Director'
);
const mainCast = movieDetails?.credits.cast.slice(0, limit) || [];
const formatCurrency = (amount: number) =>
new Intl.NumberFormat("pl-PL", {
style: "currency",
currency: "USD",
}).format(amount);
return (
<section className="blocks">
<div className="container mx-auto">
@@ -32,7 +26,7 @@ export const MovieCast: FC<Props> = ({ movieDetails }) => {
<div className="lg:col-span-2">
<h2 className="text-2xl font-bold text-white mb-6">Obsada</h2>
<div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-6">
{mainCast.map((actor) => (
{mainCast.map(actor => (
<Link
key={actor.id}
href={`/aktor/${actor.id}`}
@@ -41,12 +35,12 @@ export const MovieCast: FC<Props> = ({ movieDetails }) => {
<div className="relative overflow-hidden rounded-xl mb-3">
<img
style={{
aspectRatio: "185/278",
aspectRatio: '185/278',
}}
src={
actor.profile_path
? `https://image.tmdb.org/t/p/w185${actor.profile_path}`
: "/api/placeholder/185/278"
: '/api/placeholder/185/278'
}
alt={actor.name}
className="w-full object-cover group-hover:scale-110 transition-transform duration-500 bg-gradient-to-br from-purple-500/20 to-cyan-500/20"
@@ -147,7 +141,7 @@ export const MovieCast: FC<Props> = ({ movieDetails }) => {
<div className="space-y-2">
{movieDetails.production_companies
.slice(0, 3)
.map((company) => (
.map(company => (
<p key={company.id} className="text-gray-300">
{company.name}
</p>

View File

@@ -1,13 +1,14 @@
'use client';
import { FC, ReactNode, useState } from 'react';
import { MovieCard } from '@/components/atoms/MovieCard';
import { useGlobalStore } from '@/app/store/globalStore';
import { Dropdown } from '@/components/atoms/Dropdown';
import { useAutoAnimate } from '@formkit/auto-animate/react';
import { Button } from '@/components/atoms/Button';
import { Label } from '@/components/atoms/Label';
import { FaList } from 'react-icons/fa';
import { MovieRow } from '@/components/atoms/MovieRow';
import { useGlobalStore } from '@/app/store/global';
import { SearchInput } from '@/components/atoms/SearchInput';
type Props = {
heading?: string;
@@ -17,6 +18,7 @@ type Props = {
overrideMovies?: Movie[];
overrideDisplayType?: 'grid' | 'list';
showSearch?: boolean;
showFilters?: boolean;
filterSeen?: 0 | 1;
filterFavorites?: 0 | 1;
@@ -25,7 +27,7 @@ type Props = {
fluid?: boolean;
showSorting?: boolean;
sort?: 'title' | 'releaseDate' | 'popularity';
sort?: 'title' | 'releaseDate' | 'popularity' | 'voteAverage';
sortDirection?: 'asc' | 'desc';
loadMore?: boolean;
@@ -37,6 +39,7 @@ export const MovieList: FC<Props> = ({
colors = 'white',
overrideMovies,
showFilters = true,
showSearch = false,
filterSeen: filterSeenInitial,
filterFavorites: filterFavoritesInitial,
filterUpcoming: filterUpcomingInitial,
@@ -48,23 +51,23 @@ export const MovieList: FC<Props> = ({
loadMore = false,
overrideDisplayType,
}) => {
const {
movies: storeMovies,
displayType: displayTypeInitial,
setDisplayType,
} = useGlobalStore();
const storeMovies = useGlobalStore(state => state.movies);
const displayTypeInitial = useGlobalStore(state => state.displayType);
const setDisplayType = useGlobalStore(state => state.setDisplayType);
const movies = overrideMovies || storeMovies;
const displayType = overrideDisplayType || displayTypeInitial;
const [filter, setFilter] = useState({
search: '',
seen: filterSeenInitial,
favorites: filterFavoritesInitial,
upcoming: filterUpcomingInitial,
released: filterReleasedInitial,
});
const [sort, setSort] = useState<'title' | 'releaseDate' | 'popularity'>(
sortType
);
const [sort, setSort] = useState<
'title' | 'releaseDate' | 'popularity' | 'voteAverage'
>(sortType);
const [loaded, setLoaded] = useState(8);
const [parent] = useAutoAnimate();
@@ -88,6 +91,9 @@ export const MovieList: FC<Props> = ({
result =
result && filter.released ? releaseDate < today : releaseDate > today;
}
if (filter.search) {
result = movie.title.toLowerCase().includes(filter.search.toLowerCase());
}
return result;
});
@@ -98,6 +104,7 @@ export const MovieList: FC<Props> = ({
new Date(b.release_date).getTime() - new Date(a.release_date).getTime()
);
if (sort === 'popularity') return b.popularity - a.popularity;
if (sort === 'voteAverage') return b.vote_average - a.vote_average;
return 0;
});
@@ -108,6 +115,7 @@ export const MovieList: FC<Props> = ({
const handleFilter = (key?: keyof typeof filter) => {
setFilter({
search: '',
seen: filterSeenInitial,
favorites: filterFavoritesInitial,
upcoming: filterUpcomingInitial,
@@ -168,6 +176,7 @@ export const MovieList: FC<Props> = ({
}
onClick={() =>
setFilter({
search: '',
seen: 0,
released: 1,
favorites: filterFavoritesInitial,
@@ -215,6 +224,7 @@ export const MovieList: FC<Props> = ({
{ label: 'Tytuł', value: 'title' },
{ label: 'Data premiery', value: 'releaseDate' },
{ label: 'Popularność', value: 'popularity' },
{ label: 'Ocena', value: 'voteAverage' },
]}
defaultValue={sort}
callback={value => setSort(value as 'title')}
@@ -223,6 +233,15 @@ export const MovieList: FC<Props> = ({
)}
</div>
)}
{showSearch && (
<div className="flex justify-end mt-6">
<SearchInput
className="w-full"
placeholder="Wyszukaj film..."
onChange={value => setFilter({ ...filter, search: value })}
/>
</div>
)}
{filteredMovies.length === 0 && (
<p className="text-text/60 text-sm">Brak filmów</p>
)}

View File

@@ -1,8 +1,8 @@
'use client';
import { FC, useMemo, useState } from 'react';
import { useGlobalStore } from '@/app/store/globalStore';
import { Button } from '@/components/atoms/Button';
import { FaDice } from 'react-icons/fa';
import { useGlobalStore } from '@/app/store/global';
import Link from 'next/link';
type StoreFilter = 'all' | 'not_seen' | 'released' | 'favorites' | 'to_watch';
@@ -20,7 +20,7 @@ export const RandomMovie: FC<Props> = ({
colors = 'purple',
className = '',
}) => {
const { movies } = useGlobalStore();
const movies = useGlobalStore(state => state.movies);
const [selectedMovie, setSelectedMovie] = useState<Movie | null>(null);
// Filter movies based on the selected store filter.

View File

@@ -1,8 +1,8 @@
'use client';
import { FC } from 'react';
import { useGlobalStore } from '@/app/store/globalStore';
import { FaCalendar, FaClock } from 'react-icons/fa';
import { MovieRow } from '@/components/atoms/MovieRow';
import { useGlobalStore } from '@/app/store/global';
type Props = {
overrideMovies?: Movie[];
@@ -17,7 +17,7 @@ export const TrackedMovies: FC<Props> = ({
labelCurrent = 'Aktualnie w kinach',
labelUpcoming = 'Nadchodzące premiery',
}) => {
const { movies: storeMovies } = useGlobalStore();
const storeMovies = useGlobalStore(state => state.movies);
const movies = overrideMovies || storeMovies;

View File

@@ -8,9 +8,9 @@ import {
FaMinus,
} from 'react-icons/fa';
import { RiCalendarCheckLine, RiCalendarScheduleLine } from 'react-icons/ri';
import { useGlobalStore } from '@/app/store/globalStore';
import Link from 'next/link';
import { Button } from '@/components/atoms/Button';
import { useGlobalStore } from '@/app/store/global';
type Props = {
movies: Movie[];
@@ -28,11 +28,9 @@ export const Hero: FC<Props> = ({
const [currentIndex, setCurrentIndex] = useState(0);
const [isTransitioning, setIsTransitioning] = useState(false);
const {
movies: storedMovies,
addMovie: addMovieToStore,
deleteMovie: deleteMovieInStore,
} = useGlobalStore();
const storedMovies = useGlobalStore(state => state.movies);
const addMovie = useGlobalStore(state => state.addMovie);
const deleteMovie = useGlobalStore(state => state.deleteMovie);
const currentMovie = movies[currentIndex];
@@ -92,11 +90,11 @@ export const Hero: FC<Props> = ({
}, [autoRotate, rotateInterval, nextSlide, movies.length]);
const handleAdd = async () => {
addMovieToStore(currentMovie);
addMovie(currentMovie);
};
const handleRemove = async () => {
deleteMovieInStore(id);
deleteMovie(id);
};
return (