From 9231e0642cec0dab6a256fa05369b74a3f0b6731 Mon Sep 17 00:00:00 2001 From: Norbert Maciaszek Date: Mon, 27 Oct 2025 20:29:49 +0100 Subject: [PATCH] refactor: migrate from drizzle to PocketBase --- drizzle.config.ts | 10 - drizzle/0000_breezy_lester.sql | 11 - drizzle/0001_elite_odin.sql | 42 -- drizzle/meta/0000_snapshot.json | 94 --- drizzle/meta/0001_snapshot.json | 142 ---- drizzle/meta/_journal.json | 20 - package-lock.json | 659 +----------------- package.json | 3 +- src/app/api/movies/route.ts | 6 +- src/app/layout.tsx | 12 +- src/app/store/globalStore.tsx | 41 +- src/components/atoms/MovieCard/index.tsx | 43 +- src/components/atoms/MovieRow/index.tsx | 23 +- src/components/molecules/MovieList/index.tsx | 95 ++- .../molecules/RandomMovie/index.tsx | 2 - .../molecules/RecommendedMovies/index.tsx | 16 +- .../molecules/TrackedMovies/index.tsx | 23 +- src/components/organisms/Hero/index.tsx | 43 +- src/helpers/convertToMovie/index.ts | 10 +- src/lib/db/index.ts | 37 - src/lib/db/pb.ts | 64 ++ src/lib/db/schema.ts | 20 - src/types/global.d.ts | 22 +- 23 files changed, 240 insertions(+), 1198 deletions(-) delete mode 100644 drizzle.config.ts delete mode 100644 drizzle/0000_breezy_lester.sql delete mode 100644 drizzle/0001_elite_odin.sql delete mode 100644 drizzle/meta/0000_snapshot.json delete mode 100644 drizzle/meta/0001_snapshot.json delete mode 100644 drizzle/meta/_journal.json delete mode 100644 src/lib/db/index.ts create mode 100644 src/lib/db/pb.ts delete mode 100644 src/lib/db/schema.ts diff --git a/drizzle.config.ts b/drizzle.config.ts deleted file mode 100644 index d2ceeb9..0000000 --- a/drizzle.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { defineConfig } from "drizzle-kit"; - -export default defineConfig({ - out: "./drizzle", - schema: "./src/lib/db/schema.ts", - dialect: "sqlite", - dbCredentials: { - url: process.env.DB_FILE_NAME!, - }, -}); diff --git a/drizzle/0000_breezy_lester.sql b/drizzle/0000_breezy_lester.sql deleted file mode 100644 index 71297b5..0000000 --- a/drizzle/0000_breezy_lester.sql +++ /dev/null @@ -1,11 +0,0 @@ -CREATE TABLE `movies` ( - `id` integer PRIMARY KEY NOT NULL, - `title` text NOT NULL, - `overview` text NOT NULL, - `popularity` real NOT NULL, - `release_date` text NOT NULL, - `poster_path` text NOT NULL, - `seen` integer DEFAULT 0 NOT NULL, - `favorite` integer DEFAULT 0 NOT NULL, - `notes` text DEFAULT '' NOT NULL -); diff --git a/drizzle/0001_elite_odin.sql b/drizzle/0001_elite_odin.sql deleted file mode 100644 index a3ad041..0000000 --- a/drizzle/0001_elite_odin.sql +++ /dev/null @@ -1,42 +0,0 @@ -PRAGMA foreign_keys=OFF;--> statement-breakpoint -CREATE TABLE `__new_movies` ( - `id` integer PRIMARY KEY NOT NULL, - `title` text NOT NULL, - `adult` integer NOT NULL, - `backdrop_path` text NOT NULL, - `genre_ids` text NOT NULL, - `original_language` text NOT NULL, - `original_title` text NOT NULL, - `overview` text NOT NULL, - `popularity` real NOT NULL, - `poster_path` text NOT NULL, - `release_date` text NOT NULL, - `video` integer NOT NULL, - `vote_average` real NOT NULL, - `vote_count` integer NOT NULL, - `seen` integer DEFAULT false, - `favorite` integer DEFAULT false -); ---> statement-breakpoint -INSERT INTO `__new_movies`("id", "title", "overview", "popularity", "poster_path", "release_date", "seen", "favorite", "adult", "backdrop_path", "genre_ids", "original_language", "original_title", "video", "vote_average", "vote_count") -SELECT - "id", - "title", - "overview", - "popularity", - "poster_path", - "release_date", - "seen", - "favorite", - 0 as "adult", -- wartość domyślna - '' as "backdrop_path", -- wartość domyślna - '[]' as "genre_ids", -- wartość domyślna (pusta tablica JSON) - 'pl-PL' as "original_language", -- wartość domyślna - "title" as "original_title", -- kopiuj z title - 0 as "video", -- wartość domyślna - 0.0 as "vote_average", -- wartość domyślna - 0 as "vote_count" -- wartość domyślna -FROM `movies`;--> statement-breakpoint -DROP TABLE `movies`;--> statement-breakpoint -ALTER TABLE `__new_movies` RENAME TO `movies`;--> statement-breakpoint -PRAGMA foreign_keys=ON; \ No newline at end of file diff --git a/drizzle/meta/0000_snapshot.json b/drizzle/meta/0000_snapshot.json deleted file mode 100644 index 4c1ba14..0000000 --- a/drizzle/meta/0000_snapshot.json +++ /dev/null @@ -1,94 +0,0 @@ -{ - "version": "6", - "dialect": "sqlite", - "id": "19a2bad6-49be-485d-ac5e-291bd3d664ad", - "prevId": "00000000-0000-0000-0000-000000000000", - "tables": { - "movies": { - "name": "movies", - "columns": { - "id": { - "name": "id", - "type": "integer", - "primaryKey": true, - "notNull": true, - "autoincrement": false - }, - "title": { - "name": "title", - "type": "text", - "primaryKey": false, - "notNull": true, - "autoincrement": false - }, - "overview": { - "name": "overview", - "type": "text", - "primaryKey": false, - "notNull": true, - "autoincrement": false - }, - "popularity": { - "name": "popularity", - "type": "real", - "primaryKey": false, - "notNull": true, - "autoincrement": false - }, - "release_date": { - "name": "release_date", - "type": "text", - "primaryKey": false, - "notNull": true, - "autoincrement": false - }, - "poster_path": { - "name": "poster_path", - "type": "text", - "primaryKey": false, - "notNull": true, - "autoincrement": false - }, - "seen": { - "name": "seen", - "type": "integer", - "primaryKey": false, - "notNull": true, - "autoincrement": false, - "default": 0 - }, - "favorite": { - "name": "favorite", - "type": "integer", - "primaryKey": false, - "notNull": true, - "autoincrement": false, - "default": 0 - }, - "notes": { - "name": "notes", - "type": "text", - "primaryKey": false, - "notNull": true, - "autoincrement": false, - "default": "''" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "checkConstraints": {} - } - }, - "views": {}, - "enums": {}, - "_meta": { - "schemas": {}, - "tables": {}, - "columns": {} - }, - "internal": { - "indexes": {} - } -} \ No newline at end of file diff --git a/drizzle/meta/0001_snapshot.json b/drizzle/meta/0001_snapshot.json deleted file mode 100644 index 52c8582..0000000 --- a/drizzle/meta/0001_snapshot.json +++ /dev/null @@ -1,142 +0,0 @@ -{ - "version": "6", - "dialect": "sqlite", - "id": "c3b4d292-f58b-4df8-844c-6e534034c832", - "prevId": "19a2bad6-49be-485d-ac5e-291bd3d664ad", - "tables": { - "movies": { - "name": "movies", - "columns": { - "id": { - "name": "id", - "type": "integer", - "primaryKey": true, - "notNull": true, - "autoincrement": false - }, - "title": { - "name": "title", - "type": "text", - "primaryKey": false, - "notNull": true, - "autoincrement": false - }, - "adult": { - "name": "adult", - "type": "integer", - "primaryKey": false, - "notNull": true, - "autoincrement": false - }, - "backdrop_path": { - "name": "backdrop_path", - "type": "text", - "primaryKey": false, - "notNull": true, - "autoincrement": false - }, - "genre_ids": { - "name": "genre_ids", - "type": "text", - "primaryKey": false, - "notNull": true, - "autoincrement": false - }, - "original_language": { - "name": "original_language", - "type": "text", - "primaryKey": false, - "notNull": true, - "autoincrement": false - }, - "original_title": { - "name": "original_title", - "type": "text", - "primaryKey": false, - "notNull": true, - "autoincrement": false - }, - "overview": { - "name": "overview", - "type": "text", - "primaryKey": false, - "notNull": true, - "autoincrement": false - }, - "popularity": { - "name": "popularity", - "type": "real", - "primaryKey": false, - "notNull": true, - "autoincrement": false - }, - "poster_path": { - "name": "poster_path", - "type": "text", - "primaryKey": false, - "notNull": true, - "autoincrement": false - }, - "release_date": { - "name": "release_date", - "type": "text", - "primaryKey": false, - "notNull": true, - "autoincrement": false - }, - "video": { - "name": "video", - "type": "integer", - "primaryKey": false, - "notNull": true, - "autoincrement": false - }, - "vote_average": { - "name": "vote_average", - "type": "real", - "primaryKey": false, - "notNull": true, - "autoincrement": false - }, - "vote_count": { - "name": "vote_count", - "type": "integer", - "primaryKey": false, - "notNull": true, - "autoincrement": false - }, - "seen": { - "name": "seen", - "type": "integer", - "primaryKey": false, - "notNull": false, - "autoincrement": false, - "default": false - }, - "favorite": { - "name": "favorite", - "type": "integer", - "primaryKey": false, - "notNull": false, - "autoincrement": false, - "default": false - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "checkConstraints": {} - } - }, - "views": {}, - "enums": {}, - "_meta": { - "schemas": {}, - "tables": {}, - "columns": {} - }, - "internal": { - "indexes": {} - } -} \ No newline at end of file diff --git a/drizzle/meta/_journal.json b/drizzle/meta/_journal.json deleted file mode 100644 index a78166e..0000000 --- a/drizzle/meta/_journal.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "version": "7", - "dialect": "sqlite", - "entries": [ - { - "idx": 0, - "version": "6", - "when": 1754676538678, - "tag": "0000_breezy_lester", - "breakpoints": true - }, - { - "idx": 1, - "version": "6", - "when": 1754948246595, - "tag": "0001_elite_odin", - "breakpoints": true - } - ] -} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index b6592e1..201923c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,10 +11,10 @@ "@formkit/auto-animate": "^0.8.2", "@libsql/client": "^0.15.10", "dotenv": "^17.2.1", - "drizzle-orm": "^0.44.4", "lightgallery": "^2.9.0-beta.1", "motion": "^12.23.12", "next": "15.4.5", + "pocketbase": "^0.26.3", "react": "19.1.0", "react-dom": "19.1.0", "react-icons": "^5.5.0", @@ -25,7 +25,6 @@ "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", - "drizzle-kit": "^0.31.4", "tailwindcss": "^4", "tsx": "^4.20.3", "typescript": "^5" @@ -58,13 +57,6 @@ "node": ">=6.0.0" } }, - "node_modules/@drizzle-team/brocli": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/@drizzle-team/brocli/-/brocli-0.10.2.tgz", - "integrity": "sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w==", - "dev": true, - "license": "Apache-2.0" - }, "node_modules/@emnapi/runtime": { "version": "1.4.5", "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.5.tgz", @@ -75,442 +67,6 @@ "tslib": "^2.4.0" } }, - "node_modules/@esbuild-kit/core-utils": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/@esbuild-kit/core-utils/-/core-utils-3.3.2.tgz", - "integrity": "sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ==", - "deprecated": "Merged into tsx: https://tsx.is", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "~0.18.20", - "source-map-support": "^0.5.21" - } - }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/android-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", - "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/android-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", - "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/android-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", - "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/darwin-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", - "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/darwin-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", - "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/freebsd-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", - "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/freebsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", - "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", - "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", - "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", - "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-loong64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", - "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-mips64el": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", - "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-ppc64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", - "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-riscv64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", - "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-s390x": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", - "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", - "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/netbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", - "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/openbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", - "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/sunos-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", - "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/win32-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", - "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/win32-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", - "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/win32-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", - "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild-kit/core-utils/node_modules/esbuild": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", - "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/android-arm": "0.18.20", - "@esbuild/android-arm64": "0.18.20", - "@esbuild/android-x64": "0.18.20", - "@esbuild/darwin-arm64": "0.18.20", - "@esbuild/darwin-x64": "0.18.20", - "@esbuild/freebsd-arm64": "0.18.20", - "@esbuild/freebsd-x64": "0.18.20", - "@esbuild/linux-arm": "0.18.20", - "@esbuild/linux-arm64": "0.18.20", - "@esbuild/linux-ia32": "0.18.20", - "@esbuild/linux-loong64": "0.18.20", - "@esbuild/linux-mips64el": "0.18.20", - "@esbuild/linux-ppc64": "0.18.20", - "@esbuild/linux-riscv64": "0.18.20", - "@esbuild/linux-s390x": "0.18.20", - "@esbuild/linux-x64": "0.18.20", - "@esbuild/netbsd-x64": "0.18.20", - "@esbuild/openbsd-x64": "0.18.20", - "@esbuild/sunos-x64": "0.18.20", - "@esbuild/win32-arm64": "0.18.20", - "@esbuild/win32-ia32": "0.18.20", - "@esbuild/win32-x64": "0.18.20" - } - }, - "node_modules/@esbuild-kit/esm-loader": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/@esbuild-kit/esm-loader/-/esm-loader-2.6.5.tgz", - "integrity": "sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA==", - "deprecated": "Merged into tsx: https://tsx.is", - "dev": true, - "license": "MIT", - "dependencies": { - "@esbuild-kit/core-utils": "^3.3.2", - "get-tsconfig": "^4.7.0" - } - }, "node_modules/@esbuild/aix-ppc64": { "version": "0.25.8", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.8.tgz", @@ -2062,13 +1618,6 @@ "@types/node": "*" } }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true, - "license": "MIT" - }, "node_modules/caniuse-lite": { "version": "1.0.30001731", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001731.tgz", @@ -2166,24 +1715,6 @@ "node": ">= 12" } }, - "node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, "node_modules/dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", @@ -2215,147 +1746,6 @@ "url": "https://dotenvx.com" } }, - "node_modules/drizzle-kit": { - "version": "0.31.4", - "resolved": "https://registry.npmjs.org/drizzle-kit/-/drizzle-kit-0.31.4.tgz", - "integrity": "sha512-tCPWVZWZqWVx2XUsVpJRnH9Mx0ClVOf5YUHerZ5so1OKSlqww4zy1R5ksEdGRcO3tM3zj0PYN6V48TbQCL1RfA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@drizzle-team/brocli": "^0.10.2", - "@esbuild-kit/esm-loader": "^2.5.5", - "esbuild": "^0.25.4", - "esbuild-register": "^3.5.0" - }, - "bin": { - "drizzle-kit": "bin.cjs" - } - }, - "node_modules/drizzle-orm": { - "version": "0.44.4", - "resolved": "https://registry.npmjs.org/drizzle-orm/-/drizzle-orm-0.44.4.tgz", - "integrity": "sha512-ZyzKFpTC/Ut3fIqc2c0dPZ6nhchQXriTsqTNs4ayRgl6sZcFlMs9QZKPSHXK4bdOf41GHGWf+FrpcDDYwW+W6Q==", - "license": "Apache-2.0", - "peerDependencies": { - "@aws-sdk/client-rds-data": ">=3", - "@cloudflare/workers-types": ">=4", - "@electric-sql/pglite": ">=0.2.0", - "@libsql/client": ">=0.10.0", - "@libsql/client-wasm": ">=0.10.0", - "@neondatabase/serverless": ">=0.10.0", - "@op-engineering/op-sqlite": ">=2", - "@opentelemetry/api": "^1.4.1", - "@planetscale/database": ">=1.13", - "@prisma/client": "*", - "@tidbcloud/serverless": "*", - "@types/better-sqlite3": "*", - "@types/pg": "*", - "@types/sql.js": "*", - "@upstash/redis": ">=1.34.7", - "@vercel/postgres": ">=0.8.0", - "@xata.io/client": "*", - "better-sqlite3": ">=7", - "bun-types": "*", - "expo-sqlite": ">=14.0.0", - "gel": ">=2", - "knex": "*", - "kysely": "*", - "mysql2": ">=2", - "pg": ">=8", - "postgres": ">=3", - "sql.js": ">=1", - "sqlite3": ">=5" - }, - "peerDependenciesMeta": { - "@aws-sdk/client-rds-data": { - "optional": true - }, - "@cloudflare/workers-types": { - "optional": true - }, - "@electric-sql/pglite": { - "optional": true - }, - "@libsql/client": { - "optional": true - }, - "@libsql/client-wasm": { - "optional": true - }, - "@neondatabase/serverless": { - "optional": true - }, - "@op-engineering/op-sqlite": { - "optional": true - }, - "@opentelemetry/api": { - "optional": true - }, - "@planetscale/database": { - "optional": true - }, - "@prisma/client": { - "optional": true - }, - "@tidbcloud/serverless": { - "optional": true - }, - "@types/better-sqlite3": { - "optional": true - }, - "@types/pg": { - "optional": true - }, - "@types/sql.js": { - "optional": true - }, - "@upstash/redis": { - "optional": true - }, - "@vercel/postgres": { - "optional": true - }, - "@xata.io/client": { - "optional": true - }, - "better-sqlite3": { - "optional": true - }, - "bun-types": { - "optional": true - }, - "expo-sqlite": { - "optional": true - }, - "gel": { - "optional": true - }, - "knex": { - "optional": true - }, - "kysely": { - "optional": true - }, - "mysql2": { - "optional": true - }, - "pg": { - "optional": true - }, - "postgres": { - "optional": true - }, - "prisma": { - "optional": true - }, - "sql.js": { - "optional": true - }, - "sqlite3": { - "optional": true - } - } - }, "node_modules/enhanced-resolve": { "version": "5.18.2", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz", @@ -2412,19 +1802,6 @@ "@esbuild/win32-x64": "0.25.8" } }, - "node_modules/esbuild-register": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/esbuild-register/-/esbuild-register-3.6.0.tgz", - "integrity": "sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.3.4" - }, - "peerDependencies": { - "esbuild": ">=0.12 <1" - } - }, "node_modules/fetch-blob": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", @@ -2924,13 +2301,6 @@ "integrity": "sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ==", "license": "MIT" }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, "node_modules/nanoid": { "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", @@ -3073,6 +2443,12 @@ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "license": "ISC" }, + "node_modules/pocketbase": { + "version": "0.26.3", + "resolved": "https://registry.npmjs.org/pocketbase/-/pocketbase-0.26.3.tgz", + "integrity": "sha512-5deUKRoEczpxxuHzwr6/DHVmgbggxylEVig8CKN+MjvtYxPUqX/C6puU0yaR2yhTi8zrh7J9s7Ty+qBGwVzWOQ==", + "license": "MIT" + }, "node_modules/postcss": { "version": "8.5.6", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", @@ -3220,16 +2596,6 @@ "is-arrayish": "^0.3.1" } }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -3239,17 +2605,6 @@ "node": ">=0.10.0" } }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, "node_modules/styled-jsx": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", diff --git a/package.json b/package.json index 49e1bc4..0d11da1 100644 --- a/package.json +++ b/package.json @@ -12,10 +12,10 @@ "@formkit/auto-animate": "^0.8.2", "@libsql/client": "^0.15.10", "dotenv": "^17.2.1", - "drizzle-orm": "^0.44.4", "lightgallery": "^2.9.0-beta.1", "motion": "^12.23.12", "next": "15.4.5", + "pocketbase": "^0.26.3", "react": "19.1.0", "react-dom": "19.1.0", "react-icons": "^5.5.0", @@ -26,7 +26,6 @@ "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", - "drizzle-kit": "^0.31.4", "tailwindcss": "^4", "tsx": "^4.20.3", "typescript": "^5" diff --git a/src/app/api/movies/route.ts b/src/app/api/movies/route.ts index 776cc8a..9fc81b4 100644 --- a/src/app/api/movies/route.ts +++ b/src/app/api/movies/route.ts @@ -1,8 +1,8 @@ -import { getMovies } from "@/lib/db"; -import { NextResponse } from "next/server"; +import { DB_getMovies } from '@/lib/db/pb'; +import { NextResponse } from 'next/server'; export const GET = async () => { - const movies = await getMovies(); + const movies = await DB_getMovies(); const res = NextResponse.json(movies); return res; diff --git a/src/app/layout.tsx b/src/app/layout.tsx index eee44e5..a184fd2 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,16 +1,16 @@ -import "./globals.css"; +import './globals.css'; -import { Navbar } from "@/components/organisms/Navbar"; -import { AuroraBackground } from "@/components/effects"; -import { GlobalStoreProvider } from "./store/globalStore"; -import { getMovies } from "@/lib/db"; +import { Navbar } from '@/components/organisms/Navbar'; +import { AuroraBackground } from '@/components/effects'; +import { GlobalStoreProvider } from './store/globalStore'; +import { DB_getMovies } from '@/lib/db/pb'; export default async function RootLayout({ children, }: Readonly<{ children: React.ReactNode; }>) { - const movies = await getMovies(); + const movies = await DB_getMovies(); return ( diff --git a/src/app/store/globalStore.tsx b/src/app/store/globalStore.tsx index b288038..5d0610c 100644 --- a/src/app/store/globalStore.tsx +++ b/src/app/store/globalStore.tsx @@ -1,19 +1,16 @@ -"use client"; -import { Spinner } from "@/components/atoms/Spinner"; -import { useLocalStorage } from "@/hooks/useLocalStorage"; -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; +'use client'; +import { Spinner } from '@/components/atoms/Spinner'; +import { useLocalStorage } from '@/hooks/useLocalStorage'; +import { DB_addMovie, DB_deleteMovie, DB_updateMovie } from '@/lib/db/pb'; +import { createContext, FC, use, useEffect, useState } from 'react'; type GlobalStore = { movies: Movie[]; addMovie: (movie: Movie) => void; deleteMovie: (id: number) => void; updateMovie: (id: number, movie: Partial) => void; - displayType: "grid" | "list"; - setDisplayType: (type: "grid" | "list") => void; + displayType: 'grid' | 'list'; + setDisplayType: (type: 'grid' | 'list') => void; }; const globalStore = createContext({ @@ -21,7 +18,7 @@ const globalStore = createContext({ addMovie: () => {}, deleteMovie: () => {}, updateMovie: () => {}, - displayType: "grid", + displayType: 'grid', setDisplayType: () => {}, }); @@ -36,10 +33,10 @@ export const GlobalStoreProvider: FC = ({ }) => { // Optimistic update const [firstRender, setFirstRender] = useState(true); - const [movies, setMovies] = useState(initialMovies); + const [movies, setMovies] = useState(initialMovies); const [displayType, setDisplayType] = useLocalStorage< - GlobalStore["displayType"] - >("displayType", "grid"); + GlobalStore['displayType'] + >('displayType', 'grid'); useEffect(() => { if (firstRender) { @@ -48,22 +45,20 @@ export const GlobalStoreProvider: FC = ({ }, [firstRender]); const addMovie = async (movie: Movie) => { - if (movies.find((m) => m.id === movie.id)) return; + if (movies.find(m => m.id === movie.id)) return; - addMovieToDB(movie); - setMovies((prev) => [...prev, movie]); + DB_addMovie(movie); + setMovies(prev => [...prev, movie]); }; const deleteMovie = async (id: number) => { - deleteMovieFromDB(id); - setMovies((prev) => prev.filter((m) => m.id !== id)); + DB_deleteMovie(id); + setMovies(prev => prev.filter(m => m.id !== id)); }; const updateMovie = async (id: number, movie: Partial) => { - updateMovieInDB(id, movie); - setMovies((prev) => - prev.map((m) => (m.id === id ? { ...m, ...movie } : m)) - ); + DB_updateMovie(id, movie); + setMovies(prev => prev.map(m => (m.id === id ? { ...m, ...movie } : m))); }; return ( diff --git a/src/components/atoms/MovieCard/index.tsx b/src/components/atoms/MovieCard/index.tsx index 11279ef..90aea29 100644 --- a/src/components/atoms/MovieCard/index.tsx +++ b/src/components/atoms/MovieCard/index.tsx @@ -1,12 +1,11 @@ -"use client"; -import { FC } from "react"; -import { useGlobalStore } from "@/app/store/globalStore"; -import { Movie } from "@/types/global"; -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"; +'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'; type Props = Movie & { showDayCounter?: boolean; @@ -27,7 +26,7 @@ export const MovieCard: FC = ({ 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; @@ -35,10 +34,10 @@ export const MovieCard: FC = ({ const isReleased = new Date(movie.release_date) < new Date(); const scoreColor = vote_average >= 8 - ? "from-emerald-400 to-teal-400" + ? 'from-emerald-400 to-teal-400' : vote_average >= 6 - ? "from-yellow-400 to-orange-400" - : "from-red-400 to-pink-400"; + ? 'from-yellow-400 to-orange-400' + : 'from-red-400 to-pink-400'; const handleAdd = () => { addMovieToStore(movie); @@ -129,8 +128,8 @@ export const MovieCard: FC = ({
@@ -139,8 +138,8 @@ export const MovieCard: FC = ({
@@ -185,7 +184,7 @@ export const MovieCard: FC = ({
{isReleased ? ( @@ -194,10 +193,10 @@ export const MovieCard: FC = ({ )} - {releaseDate.toLocaleDateString("pl-PL", { - day: "numeric", - month: "short", - year: "numeric", + {releaseDate.toLocaleDateString('pl-PL', { + day: 'numeric', + month: 'short', + year: 'numeric', })}
diff --git a/src/components/atoms/MovieRow/index.tsx b/src/components/atoms/MovieRow/index.tsx index f8f3bdd..9176853 100644 --- a/src/components/atoms/MovieRow/index.tsx +++ b/src/components/atoms/MovieRow/index.tsx @@ -1,11 +1,10 @@ -"use client"; -import { formatter } from "@/helpers/formater"; -import { Movie } from "@/types/global"; -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"; +'use client'; +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'; type Props = { movie: Movie; @@ -31,7 +30,7 @@ export const MovieRow: FC = ({ ); // 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; @@ -83,7 +82,7 @@ export const MovieRow: FC = ({ dragConstraints={{ left: -80, right: 80 }} dragElastic={0.01} dragMomentum={false} - whileDrag={{ cursor: "grabbing" }} + whileDrag={{ cursor: 'grabbing' }} onDragEnd={handleDragAction} className="relative z-10" > @@ -142,8 +141,8 @@ export const MovieRow: FC = ({
{isUpcoming diff --git a/src/components/molecules/MovieList/index.tsx b/src/components/molecules/MovieList/index.tsx index e108eb9..90dbad7 100644 --- a/src/components/molecules/MovieList/index.tsx +++ b/src/components/molecules/MovieList/index.tsx @@ -1,14 +1,13 @@ -"use client"; -import { FC, ReactNode, useState } from "react"; -import { MovieCard } from "@/components/atoms/MovieCard"; -import { Movie } from "@/types/global"; -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"; +'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'; type Props = { heading?: string; @@ -16,7 +15,7 @@ type Props = { colors?: keyof typeof colorsMap; overrideMovies?: Movie[]; - overrideDisplayType?: "grid" | "list"; + overrideDisplayType?: 'grid' | 'list'; showFilters?: boolean; filterSeen?: 0 | 1; @@ -26,8 +25,8 @@ type Props = { fluid?: boolean; showSorting?: boolean; - sort?: "title" | "releaseDate" | "popularity"; - sortDirection?: "asc" | "desc"; + sort?: 'title' | 'releaseDate' | 'popularity'; + sortDirection?: 'asc' | 'desc'; loadMore?: boolean; }; @@ -35,7 +34,7 @@ type Props = { export const MovieList: FC = ({ heading, icon, - colors = "white", + colors = 'white', overrideMovies, showFilters = true, filterSeen: filterSeenInitial, @@ -44,8 +43,8 @@ export const MovieList: FC = ({ filterReleased: filterReleasedInitial, fluid = false, showSorting = true, - sort: sortType = "releaseDate", - sortDirection = "asc", + sort: sortType = 'releaseDate', + sortDirection = 'asc', loadMore = false, overrideDisplayType, }) => { @@ -63,14 +62,14 @@ export const MovieList: FC = ({ upcoming: filterUpcomingInitial, released: filterReleasedInitial, }); - const [sort, setSort] = useState<"title" | "releaseDate" | "popularity">( + const [sort, setSort] = useState<'title' | 'releaseDate' | 'popularity'>( sortType ); const [loaded, setLoaded] = useState(8); const [parent] = useAutoAnimate(); - const filteredMovies = movies.filter((movie) => { + const filteredMovies = movies.filter(movie => { let result = true; const today = new Date(); if (filter.seen !== undefined) { @@ -93,16 +92,16 @@ export const MovieList: FC = ({ }); let sortedMovies = filteredMovies.sort((a, b) => { - if (sort === "title") return a.title.localeCompare(b.title); - if (sort === "releaseDate") + if (sort === 'title') return a.title.localeCompare(b.title); + if (sort === 'releaseDate') return ( new Date(b.release_date).getTime() - new Date(a.release_date).getTime() ); - if (sort === "popularity") return b.popularity - a.popularity; + if (sort === 'popularity') return b.popularity - a.popularity; return 0; }); - if (sortDirection === "desc") { + if (sortDirection === 'desc') { sortedMovies = sortedMovies.reverse(); } sortedMovies = sortedMovies.slice(0, loadMore ? loaded : movies.length); @@ -119,7 +118,7 @@ export const MovieList: FC = ({ return (
-
+
{heading && (
{icon && ( @@ -151,17 +150,17 @@ export const MovieList: FC = ({
)} @@ -232,8 +231,8 @@ export const MovieList: FC = ({ className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-y-6 gap-3 sm:gap-6 mt-8 justify-center" ref={parent} > - {sortedMovies.map((movie) => - displayType === "grid" ? ( + {sortedMovies.map(movie => + displayType === 'grid' ? ( ) : ( @@ -258,14 +257,14 @@ export const MovieList: FC = ({ }; const colorsMap = { - white: "bg-gradient-to-r from-white to-gray-300", - yellow: "bg-gradient-to-r from-yellow-400 to-orange-400", - blue: "bg-gradient-to-r from-blue-400 to-purple-400", - green: "bg-gradient-to-r from-green-400 to-teal-400", - red: "bg-gradient-to-r from-red-400 to-pink-400", - purple: "bg-gradient-to-r from-purple-400 to-pink-400", - orange: "bg-gradient-to-r from-orange-400 to-yellow-400", - pink: "bg-gradient-to-r from-pink-400 to-purple-400", - teal: "bg-gradient-to-r from-teal-400 to-green-400", - gray: "bg-gradient-to-r from-gray-400 to-gray-400", + white: 'bg-gradient-to-r from-white to-gray-300', + yellow: 'bg-gradient-to-r from-yellow-400 to-orange-400', + blue: 'bg-gradient-to-r from-blue-400 to-purple-400', + green: 'bg-gradient-to-r from-green-400 to-teal-400', + red: 'bg-gradient-to-r from-red-400 to-pink-400', + purple: 'bg-gradient-to-r from-purple-400 to-pink-400', + orange: 'bg-gradient-to-r from-orange-400 to-yellow-400', + pink: 'bg-gradient-to-r from-pink-400 to-purple-400', + teal: 'bg-gradient-to-r from-teal-400 to-green-400', + gray: 'bg-gradient-to-r from-gray-400 to-gray-400', }; diff --git a/src/components/molecules/RandomMovie/index.tsx b/src/components/molecules/RandomMovie/index.tsx index 0bea6b4..fe3bd86 100644 --- a/src/components/molecules/RandomMovie/index.tsx +++ b/src/components/molecules/RandomMovie/index.tsx @@ -3,9 +3,7 @@ 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 { useRouter } from 'next/navigation'; import Link from 'next/link'; -import { Movie } from '@/types/global'; type StoreFilter = 'all' | 'not_seen' | 'released' | 'favorites' | 'to_watch'; diff --git a/src/components/molecules/RecommendedMovies/index.tsx b/src/components/molecules/RecommendedMovies/index.tsx index 47d6a5e..83daad6 100644 --- a/src/components/molecules/RecommendedMovies/index.tsx +++ b/src/components/molecules/RecommendedMovies/index.tsx @@ -1,9 +1,9 @@ -"use client"; -import { SearchResult } from "@/lib/tmdb/types"; -import { MovieCard } from "@/components/atoms/MovieCard"; -import { FC } from "react"; -import { FaStar } from "react-icons/fa"; -import { Carousel } from "../Carousel"; +'use client'; +import { SearchResult } from '@/lib/tmdb/types'; +import { MovieCard } from '@/components/atoms/MovieCard'; +import { FC } from 'react'; +import { FaStar } from 'react-icons/fa'; +import { Carousel } from '../Carousel'; type Props = { movies: SearchResult; @@ -26,7 +26,7 @@ export const RecommendedMovies: FC = ({ movies }) => { new Date(b.release_date).getTime() - new Date(a.release_date).getTime() ) - .map((movie) => ( + .map(movie => ( = ({ movies }) => { popularity={movie.popularity} adult={movie.adult} backdrop_path={movie.backdrop_path} - genre_ids={movie.genre_ids.join(",")} + genre_ids={movie.genre_ids.join(',')} original_language={movie.original_language} original_title={movie.original_title} video={movie.video} diff --git a/src/components/molecules/TrackedMovies/index.tsx b/src/components/molecules/TrackedMovies/index.tsx index cd22297..0cea020 100644 --- a/src/components/molecules/TrackedMovies/index.tsx +++ b/src/components/molecules/TrackedMovies/index.tsx @@ -1,9 +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 { Movie } from "@/types/global"; +'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'; type Props = { overrideMovies?: Movie[]; @@ -15,8 +14,8 @@ type Props = { export const TrackedMovies: FC = ({ overrideMovies, daysLimit = 30, - labelCurrent = "Aktualnie w kinach", - labelUpcoming = "Nadchodzące premiery", + labelCurrent = 'Aktualnie w kinach', + labelUpcoming = 'Nadchodzące premiery', }) => { const { movies: storeMovies } = useGlobalStore(); @@ -27,7 +26,7 @@ export const TrackedMovies: FC = ({ } const today = new Date(); - const upcoming = movies.filter((movie) => { + const upcoming = movies.filter(movie => { const daysSinceRelease = Math.abs( Math.floor( (new Date().getTime() - new Date(movie.release_date).getTime()) / @@ -38,7 +37,7 @@ export const TrackedMovies: FC = ({ new Date(movie.release_date) > today && daysSinceRelease <= daysLimit ); }); - const inCinema = movies.filter((movie) => { + const inCinema = movies.filter(movie => { const daysSinceRelease = Math.floor( (new Date().getTime() - new Date(movie.release_date).getTime()) / (1000 * 60 * 60 * 24) @@ -73,7 +72,7 @@ export const TrackedMovies: FC = ({ {labelCurrent} ({sortedInCinema.length})
- {sortedInCinema.map((movie) => ( + {sortedInCinema.map(movie => ( ))}
@@ -87,7 +86,7 @@ export const TrackedMovies: FC = ({ {labelUpcoming} ({sortedUpcoming.length})
- {sortedUpcoming.map((movie) => ( + {sortedUpcoming.map(movie => ( ))}
diff --git a/src/components/organisms/Hero/index.tsx b/src/components/organisms/Hero/index.tsx index 711704c..0978e84 100644 --- a/src/components/organisms/Hero/index.tsx +++ b/src/components/organisms/Hero/index.tsx @@ -1,17 +1,16 @@ -"use client"; -import { FC, useState, useEffect, useCallback } from "react"; -import { Movie } from "@/types/global"; +'use client'; +import { FC, useState, useEffect, useCallback } from 'react'; import { FaPlus, FaFire, FaChevronLeft, FaChevronRight, 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"; +} 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'; type Props = { movies: Movie[]; @@ -50,7 +49,7 @@ export const Hero: FC = ({ vote_average, } = currentMovie; - const alreadyInStore = storedMovies.find((m) => m.id === id); + const alreadyInStore = storedMovies.find(m => m.id === id); const isReleased = new Date(release_date) < new Date(); const releaseDate = new Date(release_date); @@ -58,7 +57,7 @@ export const Hero: FC = ({ if (isTransitioning) return; setIsTransitioning(true); setTimeout(() => { - setCurrentIndex((prev) => (prev + 1) % movies.length); + setCurrentIndex(prev => (prev + 1) % movies.length); setIsTransitioning(false); }, 500); }, [movies.length, isTransitioning]); @@ -67,7 +66,7 @@ export const Hero: FC = ({ if (isTransitioning) return; setIsTransitioning(true); setTimeout(() => { - setCurrentIndex((prev) => (prev - 1 + movies.length) % movies.length); + setCurrentIndex(prev => (prev - 1 + movies.length) % movies.length); setIsTransitioning(false); }, 500); }, [movies.length, isTransitioning]); @@ -108,7 +107,7 @@ export const Hero: FC = ({
= ({
{/* Poster */} @@ -176,7 +175,7 @@ export const Hero: FC = ({
{isReleased ? ( @@ -184,10 +183,10 @@ export const Hero: FC = ({ ) : ( )} - {releaseDate.toLocaleDateString("pl-PL", { - day: "numeric", - month: "long", - year: "numeric", + {releaseDate.toLocaleDateString('pl-PL', { + day: 'numeric', + month: 'long', + year: 'numeric', })}
@@ -211,12 +210,12 @@ export const Hero: FC = ({ {/* Action buttons */}
@@ -234,8 +233,8 @@ export const Hero: FC = ({ disabled={isTransitioning} className={`w-3 h-3 rounded-full transition-all duration-300 disabled:cursor-not-allowed cursor-pointer ${ index === currentIndex - ? "bg-secondary scale-125" - : "bg-white/50 hover:bg-secondary/70" + ? 'bg-secondary scale-125' + : 'bg-white/50 hover:bg-secondary/70' }`} /> ))} diff --git a/src/helpers/convertToMovie/index.ts b/src/helpers/convertToMovie/index.ts index 4b4d26b..7596e9a 100644 --- a/src/helpers/convertToMovie/index.ts +++ b/src/helpers/convertToMovie/index.ts @@ -1,5 +1,3 @@ -import { Movie } from "@/types/global"; - export const convertToMovie = ( movie: any, override?: Partial @@ -12,13 +10,13 @@ export const convertToMovie = ( id: movie.id, title: movie.title, adult: movie.adult, - backdrop_path: movie.backdrop_path || "", - genre_ids: movie.genres?.join(",") || "", + backdrop_path: movie.backdrop_path || '', + genre_ids: movie.genres?.join(',') || '', original_language: movie.original_language, original_title: movie.original_title, - overview: movie.overview || "", + overview: movie.overview || '', popularity: movie.popularity, - poster_path: movie.poster_path || "", + poster_path: movie.poster_path || '', release_date: movie.release_date, video: movie.video, vote_average: movie.vote_average, diff --git a/src/lib/db/index.ts b/src/lib/db/index.ts deleted file mode 100644 index 11a12fd..0000000 --- a/src/lib/db/index.ts +++ /dev/null @@ -1,37 +0,0 @@ -"use server"; -import { drizzle } from "drizzle-orm/libsql"; -import { movies } from "./schema"; -import { eq } from "drizzle-orm"; -import { Movie } from "@/types/global"; -import { revalidatePath } from "next/cache"; - -const db = drizzle(process.env.DB_FILE_NAME!); - -export const getMovies = async () => { - return await db.select().from(movies).$withCache(); -}; - -export const addMovieToDB = async (movie: Movie) => { - await db - .insert(movies) - .values({ - ...movie, - genre_ids: JSON.stringify(movie.genre_ids), - }) - .onConflictDoNothing(); - - revalidatePath("/", "layout"); -}; - -export const deleteMovieFromDB = async (id: number) => { - await db.delete(movies).where(eq(movies.id, id)); - revalidatePath("/", "layout"); -}; - -export const updateMovieInDB = async ( - movieId: number, - movie: Partial -) => { - await db.update(movies).set(movie).where(eq(movies.id, movieId)); - revalidatePath("/", "layout"); -}; diff --git a/src/lib/db/pb.ts b/src/lib/db/pb.ts new file mode 100644 index 0000000..009186d --- /dev/null +++ b/src/lib/db/pb.ts @@ -0,0 +1,64 @@ +'use server'; +import { revalidatePath } from 'next/cache'; +import PocketBase from 'pocketbase'; + +const pb = new PocketBase(process.env.POCKET_URL!); + +const collection = 'movies_prod'; + +type CollectionMovie = Movie & { + id_imdb: number; +}; + +export const DB_getMovies = async () => { + const records = await pb.collection(collection).getFullList({ + sort: '-created', + }); + + return records.map(record => ({ + ...record, + id: record.id_imdb, + })) as Movie[]; +}; + +export const DB_addMovie = async (movie: Movie) => { + try { + await pb.collection(collection).create({ + ...movie, + id: undefined, + id_imdb: movie.id, + genre_ids: JSON.stringify(movie.genre_ids), + }); + revalidatePath('/', 'layout'); + } catch (error) { + console.error(error); + } +}; + +export const DB_deleteMovie = async (id: number) => { + try { + const record = await pb + .collection(collection) + .getFirstListItem(`id_imdb = "${id}"`); + await pb.collection(collection).delete(record.id.toString()); + revalidatePath('/', 'layout'); + } catch (error) { + console.error(error); + } +}; + +export const DB_updateMovie = async (id: number, movie: Partial) => { + try { + const record = await pb + .collection(collection) + .getFirstListItem(`id_imdb = "${id}"`); + await pb + .collection(collection) + .update(record.id.toString(), { + ...movie, + }); + revalidatePath('/', 'layout'); + } catch (error) { + console.error(error); + } +}; diff --git a/src/lib/db/schema.ts b/src/lib/db/schema.ts deleted file mode 100644 index a36c545..0000000 --- a/src/lib/db/schema.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { integer, real, sqliteTable, text } from "drizzle-orm/sqlite-core"; - -export const movies = sqliteTable("movies", { - id: integer("id").primaryKey(), - title: text("title").notNull(), - adult: integer("adult", { mode: "boolean" }).notNull(), - backdrop_path: text("backdrop_path").notNull(), - genre_ids: text("genre_ids").notNull(), - original_language: text("original_language").notNull(), - original_title: text("original_title").notNull(), - overview: text("overview").notNull(), - popularity: real("popularity").notNull(), - poster_path: text("poster_path").notNull(), - release_date: text("release_date").notNull(), - video: integer("video", { mode: "boolean" }).notNull(), - vote_average: real("vote_average").notNull(), - vote_count: integer("vote_count").notNull(), - seen: integer("seen", { mode: "boolean" }).default(false), - favorite: integer("favorite", { mode: "boolean" }).default(false), -}); diff --git a/src/types/global.d.ts b/src/types/global.d.ts index 7b1d808..6a1df79 100644 --- a/src/types/global.d.ts +++ b/src/types/global.d.ts @@ -1,4 +1,18 @@ -import { movies } from "@/lib/db/schema"; -import { SearchResult } from "@/lib/tmdb/types"; - -type Movie = typeof movies.$inferSelect; +type Movie = { + id: number; + title: string; + adult: boolean; + backdrop_path: string; + genre_ids: string; + original_language: string; + original_title: string; + overview: string; + popularity: number; + poster_path: string; + release_date: string; + video: boolean; + vote_average: number; + vote_count: number; + seen: boolean; + favorite: boolean; +};