Browse Source

Finish playlist page

features/playlist
Astri4-4 4 months ago
parent
commit
a9c8af837d
  1. 58
      backend/app/controllers/playlist.controller.js
  2. 30
      backend/app/utils/database.js
  3. 779
      backend/logs/access.log
  4. 1
      frontend/src/assets/svg/trash.svg
  5. 1
      frontend/src/components/Navbar.jsx
  6. 2
      frontend/src/components/PlaylistCard.jsx
  7. 4
      frontend/src/components/TrendingVideos.jsx
  8. 16
      frontend/src/components/VideoCard.jsx
  9. 27
      frontend/src/modals/VerificationModal.jsx
  10. 12
      frontend/src/pages/Account.jsx
  11. 97
      frontend/src/pages/Playlist.jsx
  12. 61
      frontend/src/pages/Video.jsx
  13. 9
      frontend/src/routes/routes.jsx
  14. 81
      frontend/src/services/playlist.service.js

58
backend/app/controllers/playlist.controller.js

@ -83,7 +83,63 @@ export async function getById(req, res) {
const logger = req.body.logger; const logger = req.body.logger;
const client = await getClient(); const client = await getClient();
const query = `SELECT * FROM playlists WHERE id = $1`; const query = `
SELECT
playlists.id,
playlists.name,
COALESCE(
JSON_AGG(
JSON_BUILD_OBJECT(
'id', video_data.id,
'title', video_data.title,
'thumbnail', video_data.thumbnail,
'video_description', video_data.description,
'channel', video_data.channel,
'visibility', video_data.visibility,
'file', video_data.file,
'slug', video_data.slug,
'format', video_data.format,
'release_date', video_data.release_date,
'channel_id', video_data.channel,
'owner', channels.owner,
'views', CAST(video_data.views AS TEXT),
'creator', JSON_BUILD_OBJECT(
'name', channels.name,
'profilePicture', users.picture,
'description', channels.description
),
'type', 'video'
)
) FILTER (WHERE video_data.id IS NOT NULL),
'[]'::json
) AS videos
FROM
playlists
LEFT JOIN playlist_elements ON playlists.id = playlist_elements.playlist
LEFT JOIN (
SELECT
videos.id,
videos.title,
videos.description,
videos.thumbnail,
videos.release_date,
videos.visibility,
videos.file,
videos.slug,
videos.format,
videos.channel,
COUNT(history.id) AS views
FROM videos
LEFT JOIN history ON history.video = videos.id
GROUP BY videos.id, videos.title, videos.description, videos.thumbnail, videos.release_date, videos.visibility, videos.file, videos.slug, videos.format, videos.channel
) video_data ON playlist_elements.video = video_data.id
LEFT JOIN channels ON video_data.channel = channels.id
LEFT JOIN users ON channels.owner = users.id
WHERE
playlists.id = $1
GROUP BY
playlists.id;
`;
try { try {
const result = await client.query(query, [id]); const result = await client.query(query, [id]);

30
backend/app/utils/database.js

@ -31,7 +31,7 @@ export async function initDb() {
id SERIAL PRIMARY KEY, id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL,
description TEXT NOT NULL, description TEXT NOT NULL,
owner INTEGER NOT NULL REFERENCES users(id) owner INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE
)` )`
await client.query(query); await client.query(query);
@ -40,7 +40,7 @@ export async function initDb() {
title VARCHAR(255) NOT NULL, title VARCHAR(255) NOT NULL,
thumbnail VARCHAR(255) NOT NULL, thumbnail VARCHAR(255) NOT NULL,
description TEXT NOT NULL, description TEXT NOT NULL,
channel INTEGER NOT NULL REFERENCES channels(id), channel INTEGER NOT NULL REFERENCES channels(id) ON DELETE CASCADE,
visibility VARCHAR(50) NOT NULL DEFAULT 'public', visibility VARCHAR(50) NOT NULL DEFAULT 'public',
file VARCHAR(255) NOT NULL, file VARCHAR(255) NOT NULL,
slug VARCHAR(255) NOT NULL, slug VARCHAR(255) NOT NULL,
@ -53,16 +53,16 @@ export async function initDb() {
( (
id SERIAL PRIMARY KEY, id SERIAL PRIMARY KEY,
content TEXT NOT NULL, content TEXT NOT NULL,
author INTEGER NOT NULL REFERENCES users(id), author INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
video INTEGER NOT NULL REFERENCES videos(id), video INTEGER NOT NULL REFERENCES videos(id) ON DELETE CASCADE,
created_at TIMESTAMP NOT NULL DEFAULT NOW() created_at TIMESTAMP NOT NULL DEFAULT NOW()
)`; )`;
await client.query(query); await client.query(query);
query = `CREATE TABLE IF NOT EXISTS likes ( query = `CREATE TABLE IF NOT EXISTS likes (
id SERIAL PRIMARY KEY, id SERIAL PRIMARY KEY,
owner INTEGER NOT NULL REFERENCES users(id), owner INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
video INTEGER NOT NULL REFERENCES videos(id), video INTEGER NOT NULL REFERENCES videos(id) ON DELETE CASCADE,
created_at TIMESTAMP NOT NULL DEFAULT NOW() created_at TIMESTAMP NOT NULL DEFAULT NOW()
);`; );`;
await client.query(query); await client.query(query);
@ -70,21 +70,21 @@ export async function initDb() {
query = `CREATE TABLE IF NOT EXISTS playlists ( query = `CREATE TABLE IF NOT EXISTS playlists (
id SERIAL PRIMARY KEY, id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL,
owner INTEGER NOT NULL REFERENCES users(id) owner INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE
)`; )`;
await client.query(query); await client.query(query);
query = `CREATE TABLE IF NOT EXISTS playlist_elements ( query = `CREATE TABLE IF NOT EXISTS playlist_elements (
id SERIAL PRIMARY KEY, id SERIAL PRIMARY KEY,
video INTEGER NOT NULL REFERENCES videos(id), video INTEGER NOT NULL REFERENCES videos(id) ON DELETE CASCADE,
playlist INTEGER NOT NULL REFERENCES playlists(id) playlist INTEGER NOT NULL REFERENCES playlists(id) ON DELETE CASCADE
)`; )`;
await client.query(query); await client.query(query);
query = `CREATE TABLE IF NOT EXISTS subscriptions ( query = `CREATE TABLE IF NOT EXISTS subscriptions (
id SERIAL PRIMARY KEY, id SERIAL PRIMARY KEY,
channel INTEGER NOT NULL REFERENCES channels(id), channel INTEGER NOT NULL REFERENCES channels(id) ON DELETE CASCADE,
owner INTEGER NOT NULL REFERENCES users(id) owner INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE
)`; )`;
await client.query(query); await client.query(query);
@ -96,15 +96,15 @@ export async function initDb() {
await client.query(query); await client.query(query);
query = `CREATE TABLE IF NOT EXISTS video_tags ( query = `CREATE TABLE IF NOT EXISTS video_tags (
video INTEGER NOT NULL REFERENCES videos(id), video INTEGER NOT NULL REFERENCES videos(id) ON DELETE CASCADE,
tag INTEGER NOT NULL REFERENCES tags(id) tag INTEGER NOT NULL REFERENCES tags(id) ON DELETE CASCADE
)` )`
await client.query(query); await client.query(query);
query = `CREATE TABLE IF NOT EXISTS history ( query = `CREATE TABLE IF NOT EXISTS history (
id SERIAL PRIMARY KEY, id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users(id), user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
video INTEGER NOT NULL REFERENCES videos(id), video INTEGER NOT NULL REFERENCES videos(id) ON DELETE CASCADE,
viewed_at TIMESTAMP NOT NULL DEFAULT NOW() viewed_at TIMESTAMP NOT NULL DEFAULT NOW()
)`; )`;
await client.query(query); await client.query(query);

779
backend/logs/access.log

@ -5654,3 +5654,782 @@
[2025-08-14 20:41:50.539] [undefined] GET(/:id/history): failed to retrieve history of user 6 because it doesn't exist with status 404 [2025-08-14 20:41:50.539] [undefined] GET(/:id/history): failed to retrieve history of user 6 because it doesn't exist with status 404
[2025-08-14 20:41:50.550] [undefined] GET(/user/:id): Playlists retrieved for user with id 6 with status 200 [2025-08-14 20:41:50.550] [undefined] GET(/user/:id): Playlists retrieved for user with id 6 with status 200
[2025-08-14 20:41:53.692] [undefined] POST(/): Playlist created with id 7 with status 200 [2025-08-14 20:41:53.692] [undefined] POST(/): Playlist created with id 7 with status 200
[2025-08-15 07:15:46.354] [undefined] POST(/login): try to login with username 'sacha2'
[2025-08-15 07:15:46.413] [undefined] POST(/login): Successfully logged in with status 200
[2025-08-15 07:16:04.703] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 07:16:04.706] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 07:16:04.709] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 07:16:04.714] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 07:16:04.722] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:16:25.767] [undefined] POST(/): Playlist created with id 8 with status 200
[2025-08-15 07:16:26.987] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 07:16:26.989] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 07:16:26.991] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 07:16:26.995] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 07:16:27.006] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:17:15.294] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 07:17:15.298] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 07:17:15.322] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 07:17:15.327] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 07:17:15.333] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:17:22.303] [undefined] POST(/): Playlist created with id 9 with status 200
[2025-08-15 07:17:22.321] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:17:41.905] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 07:17:41.908] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 07:17:41.916] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 07:17:41.921] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 07:17:41.927] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:17:43.230] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 07:17:43.233] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 07:17:43.258] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 07:17:43.261] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 07:17:43.269] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:17:44.606] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 07:17:44.609] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 07:17:44.612] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 07:17:44.616] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 07:17:44.623] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:17:45.539] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 07:17:45.543] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 07:17:45.545] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 07:17:45.549] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 07:17:45.556] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:18:53.759] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:18:53.769] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:18:53.782] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:18:53.794] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:18:53.821] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:18:53.832] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:19:35.214] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:19:35.225] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:19:35.238] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:19:35.251] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:19:35.273] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:19:35.284] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:19:46.027] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:19:46.037] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:19:46.050] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:19:46.068] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:19:46.093] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:19:46.101] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:21:30.310] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:21:30.320] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:21:30.333] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:21:30.348] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:21:30.386] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:21:30.395] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:21:32.380] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:21:32.390] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:21:32.403] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:21:32.418] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:21:32.441] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:21:32.449] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:21:43.838] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:21:43.848] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:21:43.860] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:21:43.876] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:21:43.916] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:21:43.925] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:22:08.679] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:22:08.689] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:22:08.701] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:22:08.716] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:22:08.747] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:22:08.757] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:22:21.736] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:22:21.747] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:22:21.762] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:22:21.777] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:22:21.802] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:22:21.811] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:22:43.624] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:22:43.634] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:22:43.647] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:22:43.662] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:22:43.692] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:22:43.703] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:23:56.553] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:23:56.564] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:23:56.577] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:23:56.591] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:23:56.613] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:23:56.622] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:26:28.747] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:26:28.757] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:26:28.770] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:26:28.798] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:26:28.834] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:26:28.843] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:26:36.036] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:26:36.047] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:26:36.063] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:26:36.075] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:26:36.122] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:26:36.132] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:27:02.346] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:27:02.357] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:27:02.360] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:27:02.374] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:27:02.385] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:27:02.417] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:27:02.428] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:28:53.335] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:28:53.346] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:28:53.351] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:28:53.366] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:28:53.382] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:28:53.407] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:28:53.415] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:29:06.301] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:29:06.311] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:29:06.315] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:29:06.327] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:29:06.341] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:29:06.370] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:29:06.380] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:29:14.077] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:29:14.088] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:29:14.092] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:29:14.109] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:29:14.124] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:29:14.156] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:29:14.165] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:29:23.599] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:29:23.610] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:29:23.614] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:29:23.630] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:29:23.643] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:29:23.669] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:29:23.677] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:29:34.032] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:29:34.042] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:29:34.047] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:29:34.061] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:29:34.075] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:29:34.117] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:29:34.127] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:29:46.216] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:29:46.227] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:29:46.232] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:29:46.251] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:29:46.265] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:29:46.287] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:29:46.297] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:30:08.411] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:30:08.421] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:30:08.425] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:30:08.438] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:30:08.451] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:30:08.495] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:30:08.504] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:30:17.869] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:30:17.880] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:30:17.899] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:30:17.911] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:30:17.926] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:30:17.956] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:30:17.966] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:30:49.412] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:30:49.422] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:30:49.427] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:30:49.438] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:30:49.453] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:30:49.477] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:30:49.493] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:31:32.628] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:31:32.640] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:31:32.645] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:31:32.659] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:31:32.674] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:31:32.704] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:31:32.713] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:32:10.030] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:32:10.041] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:32:10.045] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:32:10.057] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:32:10.070] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:32:10.105] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:32:10.115] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:32:30.091] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:32:30.102] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:32:30.927] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:32:39.410] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:32:39.424] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:32:39.432] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:32:39.447] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:32:39.465] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:32:39.492] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:32:39.502] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:33:07.385] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:33:07.396] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:33:07.401] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:33:07.417] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:33:07.431] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:33:07.470] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:33:07.480] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:33:20.298] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:33:20.309] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:33:20.315] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:33:20.332] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:33:20.350] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:33:20.373] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:33:20.383] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:33:27.995] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:33:28.007] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:33:28.012] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:33:28.026] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:33:28.042] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:33:28.076] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:33:28.086] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:33:33.605] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:33:33.615] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:33:33.620] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:33:33.631] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:33:33.646] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:33:33.677] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:33:33.689] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:33:47.482] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:33:47.493] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:33:47.497] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:33:47.511] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:33:47.527] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:33:47.551] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:33:47.559] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:33:53.695] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:33:53.707] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:33:53.724] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:33:53.737] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:33:53.751] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:33:53.780] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:33:53.791] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:33:57.653] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:33:57.665] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:33:57.670] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:33:57.683] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:33:57.700] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:33:57.725] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:33:57.733] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:34:08.528] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:34:08.538] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:34:08.543] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:34:08.556] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:34:08.569] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:34:08.616] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:34:08.625] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:35:58.474] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:35:58.485] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:35:58.490] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:35:58.504] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:35:58.522] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:35:58.544] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:35:58.553] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:36:12.736] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:36:12.747] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:36:12.752] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:36:12.764] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:36:12.778] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:36:12.799] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:36:12.809] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:36:23.117] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:36:23.128] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:36:23.133] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:36:23.145] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:36:23.160] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:36:23.192] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:36:23.202] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:36:35.456] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:36:35.467] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:36:35.472] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:36:35.486] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:36:35.501] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:36:35.545] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:36:35.554] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:38:52.975] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:38:52.987] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:38:52.993] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:38:53.007] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:38:53.022] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:38:53.053] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:38:53.066] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:39:16.059] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:39:16.071] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:39:16.077] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:39:16.091] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:39:16.105] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:39:16.149] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:39:16.160] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:39:34.058] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:39:34.069] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:39:34.073] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:39:34.088] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:39:34.105] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:39:34.130] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:39:34.141] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:40:05.198] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:40:05.209] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:40:05.213] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:40:05.227] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:40:05.244] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:40:05.279] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:40:05.289] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:40:22.330] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:40:22.342] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:40:22.347] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:40:22.361] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:40:22.376] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:40:22.400] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:40:22.409] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:43:58.684] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:43:58.695] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:43:58.699] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:43:58.713] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:43:58.728] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:43:58.771] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:43:58.781] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:44:11.725] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:44:11.737] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:44:11.742] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:44:11.762] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:44:11.775] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:44:11.810] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:44:11.819] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:44:33.503] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:44:33.515] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:44:33.520] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:44:33.542] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:44:33.557] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:44:33.628] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:44:33.640] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:45:01.108] [undefined] GET(/:id): try to get video 3
[2025-08-15 07:45:01.118] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:45:01.123] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-08-15 07:45:01.140] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-08-15 07:45:01.153] [undefined] GET(/:id/similar): successfully get similar videos for video 3 with status 200
[2025-08-15 07:45:01.185] [undefined] GET(/:id/views): try to add views for video 3
[2025-08-15 07:45:01.194] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-08-15 07:45:03.398] [undefined] POST(/:id): Video added to playlist with id 2 with status 200
[2025-08-15 07:45:12.544] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 07:45:12.548] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 07:45:12.551] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 07:45:12.554] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 07:45:12.561] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:45:18.685] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 07:45:18.688] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 07:45:18.691] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 07:45:18.695] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 07:45:18.703] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:46:57.187] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 07:46:57.191] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 07:46:57.195] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 07:46:57.201] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 07:46:57.207] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:53:09.712] [undefined] GET(/:id): Playlist retrieved with id 2 with status 200
[2025-08-15 07:57:29.629] [undefined] GET(/:id): try to get video 10
[2025-08-15 07:57:29.640] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 07:57:29.645] [undefined] GET(/:id): successfully get video 10 with status 200
[2025-08-15 07:57:29.661] [undefined] GET(/:id/similar): try to get similar videos for video 10
[2025-08-15 07:57:29.673] [undefined] GET(/:id/similar): successfully get similar videos for video 10 with status 200
[2025-08-15 07:57:29.702] [undefined] GET(/:id/views): try to add views for video 10
[2025-08-15 07:57:29.714] [undefined] GET(/:id/views): successfully added views for video 10 with status 200
[2025-08-15 07:57:31.756] [undefined] POST(/:id): Video added to playlist with id 2 with status 200
[2025-08-15 08:01:04.884] [undefined] GET(/:id): try to get video 10
[2025-08-15 08:01:04.895] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 08:01:04.902] [undefined] GET(/:id): successfully get video 10 with status 200
[2025-08-15 08:01:04.924] [undefined] GET(/:id/similar): try to get similar videos for video 10
[2025-08-15 08:01:04.942] [undefined] GET(/:id/similar): successfully get similar videos for video 10 with status 200
[2025-08-15 08:01:04.989] [undefined] GET(/:id/views): try to add views for video 10
[2025-08-15 08:01:04.998] [undefined] GET(/:id/views): successfully added views for video 10 with status 200
[2025-08-15 08:01:08.034] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 08:01:08.037] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 08:01:08.041] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 08:01:08.046] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 08:01:08.053] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 08:01:09.580] [undefined] GET(/:id): Playlist retrieved with id 2 with status 200
[2025-08-15 08:09:51.858] [undefined] GET(/:id): Playlist retrieved with id 2 with status 200
[2025-08-15 08:10:08.586] [undefined] GET(/:id): Playlist retrieved with id 2 with status 200
[2025-08-15 08:10:21.732] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 08:10:21.736] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 08:10:21.739] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 08:10:21.746] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 08:10:21.753] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 08:11:01.489] [undefined] GET(/:id): Error retrieving playlist: missing FROM-clause entry for table "channel" with status 500
[2025-08-15 08:11:36.075] [undefined] GET(/:id): Playlist retrieved with id 2 with status 200
[2025-08-15 11:34:51.115] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 11:34:51.118] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 11:34:51.126] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 11:34:51.132] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 11:34:51.141] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 11:34:52.476] [undefined] GET(/:id): Playlist retrieved with id 2 with status 200
[2025-08-15 11:36:02.596] [undefined] GET(/:id): Playlist retrieved with id 2 with status 200
[2025-08-15 11:36:12.642] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 11:36:12.646] [undefined] GET(/:id): try to get video 7
[2025-08-15 11:36:12.657] [undefined] GET(/:id): successfully get video 7 with status 200
[2025-08-15 11:36:12.669] [undefined] GET(/:id/similar): try to get similar videos for video 7
[2025-08-15 11:36:12.685] [undefined] GET(/:id/similar): successfully get similar videos for video 7 with status 200
[2025-08-15 11:36:12.709] [undefined] GET(/:id/views): try to add views for video 7
[2025-08-15 11:36:12.721] [undefined] GET(/:id/views): successfully added views for video 7 with status 200
[2025-08-15 11:36:15.330] [undefined] POST(/:id): Video added to playlist with id 9 with status 200
[2025-08-15 11:36:16.992] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 11:36:16.996] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 11:36:16.999] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 11:36:17.004] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 11:36:17.010] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 11:36:19.673] [undefined] GET(/:id): Playlist retrieved with id 9 with status 200
[2025-08-15 11:36:21.015] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 11:36:21.017] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 11:36:21.020] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 11:36:21.024] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 11:36:21.031] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 11:37:36.685] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 11:37:36.688] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 11:37:36.691] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 11:37:36.697] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 11:37:36.704] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 11:37:37.540] [undefined] GET(/:id): Playlist retrieved with id 9 with status 200
[2025-08-15 11:37:46.171] [undefined] GET(/:id): try to get video 7
[2025-08-15 11:37:46.181] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 11:37:46.186] [undefined] GET(/:id): successfully get video 7 with status 200
[2025-08-15 11:37:46.197] [undefined] GET(/:id/similar): try to get similar videos for video 7
[2025-08-15 11:37:46.211] [undefined] GET(/:id/similar): successfully get similar videos for video 7 with status 200
[2025-08-15 11:37:46.241] [undefined] GET(/:id/views): try to add views for video 7
[2025-08-15 11:37:46.251] [undefined] GET(/:id/views): successfully added views for video 7 with status 200
[2025-08-15 11:37:46.753] [undefined] GET(/:id): Playlist retrieved with id 9 with status 200
[2025-08-15 11:37:48.179] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 11:37:48.182] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 11:37:48.184] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 11:37:48.189] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 11:37:48.197] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 11:38:45.205] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 11:38:45.208] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 11:38:45.217] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 11:38:45.221] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 11:38:45.228] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 11:39:25.429] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 11:39:25.432] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 11:39:25.436] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 11:39:25.441] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 11:39:25.447] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 11:39:33.775] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 11:39:33.780] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 11:39:33.783] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 11:39:33.788] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 11:39:33.796] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 11:39:42.483] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 11:39:42.487] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 11:39:42.492] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 11:39:42.499] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 11:39:42.506] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 11:39:54.583] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 11:39:54.587] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 11:39:54.590] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 11:39:54.597] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 11:39:54.604] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 11:40:01.578] [undefined] GET(/:id): Playlist retrieved with id 8 with status 200
[2025-08-15 11:40:02.989] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 11:40:02.992] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 11:40:02.996] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 11:40:03.001] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 11:40:03.006] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 11:40:03.583] [undefined] GET(/:id): Playlist retrieved with id 8 with status 200
[2025-08-15 11:40:04.040] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 11:40:04.044] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 11:40:04.047] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 11:40:04.050] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 11:40:04.058] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 11:40:04.695] [undefined] GET(/:id): Playlist retrieved with id 9 with status 200
[2025-08-15 11:40:05.139] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 11:40:05.142] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 11:40:05.145] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 11:40:05.149] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 11:40:05.156] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 11:40:05.674] [undefined] GET(/:id): Playlist retrieved with id 2 with status 200
[2025-08-15 11:40:06.063] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 11:40:06.067] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 11:40:06.070] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 11:40:06.074] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 11:40:06.082] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 11:40:06.616] [undefined] GET(/:id): Playlist retrieved with id 8 with status 200
[2025-08-15 11:40:32.573] [undefined] GET(/:id): Playlist retrieved with id 8 with status 200
[2025-08-15 11:40:33.203] [undefined] GET(/:id): Playlist retrieved with id 8 with status 200
[2025-08-15 11:40:33.945] [undefined] GET(/:id): Playlist retrieved with id 8 with status 200
[2025-08-15 11:40:45.160] [undefined] GET(/:id): Playlist retrieved with id 8 with status 200
[2025-08-15 11:40:45.922] [undefined] GET(/:id): Playlist retrieved with id 8 with status 200
[2025-08-15 11:40:51.863] [undefined] GET(/:id): Playlist retrieved with id 8 with status 200
[2025-08-15 11:41:01.257] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 11:41:01.260] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 11:41:01.264] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 11:41:01.269] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 11:41:01.277] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 11:42:23.314] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 11:42:23.319] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 11:42:23.344] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 11:42:23.351] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 11:42:23.358] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 11:42:24.351] [undefined] GET(/:id): Playlist retrieved with id 8 with status 200
[2025-08-15 11:42:27.415] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 11:42:27.419] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 11:42:27.427] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 11:42:27.432] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 11:42:27.439] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 11:42:28.016] [undefined] GET(/:id): Playlist retrieved with id 2 with status 200
[2025-08-15 11:42:28.584] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 11:42:28.587] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 11:42:28.591] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 11:42:28.595] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 11:42:28.600] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 11:42:29.091] [undefined] GET(/:id): Playlist retrieved with id 8 with status 200
[2025-08-15 11:42:30.125] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 11:42:30.129] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 11:42:30.131] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 11:42:30.136] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 11:42:30.144] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 11:42:55.444] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 11:42:55.447] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 11:42:55.450] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 11:42:55.454] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 11:42:55.462] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 11:42:55.946] [undefined] GET(/:id): Playlist retrieved with id 2 with status 200
[2025-08-15 11:43:04.667] [undefined] GET(/:id): Playlist retrieved with id 2 with status 200
[2025-08-15 11:43:25.896] [undefined] GET(/:id): Playlist retrieved with id 2 with status 200
[2025-08-15 11:44:01.336] [undefined] GET(/:id): Playlist retrieved with id 2 with status 200
[2025-08-15 11:44:08.744] [undefined] GET(/:id): Playlist retrieved with id 2 with status 200
[2025-08-15 11:44:40.681] [undefined] GET(/:id): Playlist retrieved with id 2 with status 200
[2025-08-15 11:44:51.683] [undefined] GET(/:id): Playlist retrieved with id 2 with status 200
[2025-08-15 11:45:09.918] [undefined] GET(/:id): Playlist retrieved with id 2 with status 200
[2025-08-15 11:45:17.445] [undefined] GET(/:id): Playlist retrieved with id 2 with status 200
[2025-08-15 11:45:23.115] [undefined] GET(/:id): Playlist retrieved with id 2 with status 200
[2025-08-15 11:46:00.470] [undefined] GET(/:id): Playlist retrieved with id 2 with status 200
[2025-08-15 11:46:03.102] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 11:46:03.105] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 11:46:03.107] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 11:46:03.113] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 11:46:03.121] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 11:46:06.450] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 11:46:07.270] [undefined] GET(/:id): Playlist retrieved with id 2 with status 200
[2025-08-15 11:51:55.980] [undefined] GET(/:id): Playlist retrieved with id 2 with status 200
[2025-08-15 11:52:34.410] [undefined] GET(/:id): Playlist retrieved with id 2 with status 200
[2025-08-15 11:52:49.764] [undefined] GET(/:id): Playlist retrieved with id 2 with status 200
[2025-08-15 11:52:59.942] [undefined] GET(/:id): Playlist retrieved with id 2 with status 200
[2025-08-15 11:53:14.793] [undefined] GET(/:id): Playlist retrieved with id 2 with status 200
[2025-08-15 11:53:23.643] [undefined] GET(/:id): Playlist retrieved with id 2 with status 200
[2025-08-15 11:53:42.731] [undefined] GET(/:id): Playlist retrieved with id 2 with status 200
[2025-08-15 11:54:00.339] [undefined] GET(/:id): Playlist retrieved with id 2 with status 200
[2025-08-15 11:54:35.499] [undefined] GET(/:id): Playlist retrieved with id 2 with status 200
[2025-08-15 11:54:53.925] [undefined] GET(/:id): Playlist retrieved with id 2 with status 200
[2025-08-15 11:55:09.339] [undefined] GET(/:id): Playlist retrieved with id 2 with status 200
[2025-08-15 11:55:22.887] [undefined] GET(/:id): Playlist retrieved with id 2 with status 200
[2025-08-15 11:56:17.396] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 11:56:17.401] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 11:56:17.407] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 11:56:17.411] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 11:56:17.418] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 11:56:18.071] [undefined] GET(/:id): Playlist retrieved with id 8 with status 200
[2025-08-15 11:56:43.895] [undefined] GET(/:id): Playlist retrieved with id 8 with status 200
[2025-08-15 11:57:03.654] [undefined] GET(/:id): Playlist retrieved with id 8 with status 200
[2025-08-15 11:57:05.682] [undefined] DELETE(/:id): Playlist deleted with status 200
[2025-08-15 11:57:07.595] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 11:57:07.598] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 11:57:07.601] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 11:57:07.606] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 11:57:07.614] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 11:57:27.626] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 11:57:27.630] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 11:57:27.634] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 11:57:27.641] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 11:57:27.650] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 11:57:31.598] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 11:57:31.602] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 11:57:31.605] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 11:57:31.611] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 11:57:31.616] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 11:57:45.169] [undefined] GET(/:id): Playlist retrieved with id 9 with status 200
[2025-08-15 11:57:49.098] [undefined] DELETE(/:id): Error deleting playlist: update or delete on table "playlists" violates foreign key constraint "playlist_elements_playlist_fkey" on table "playlist_elements" with status 500
[2025-08-15 11:57:49.135] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 11:57:49.139] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 11:57:49.141] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 11:57:49.147] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 11:57:49.156] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 11:57:50.662] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 11:57:50.665] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 11:57:50.668] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 11:57:50.674] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 11:57:50.680] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 11:57:51.421] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 11:57:51.424] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 11:57:51.427] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 11:57:51.431] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 11:57:51.439] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 11:57:52.853] [undefined] GET(/:id): Playlist retrieved with id 9 with status 200
[2025-08-15 11:57:53.587] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 11:57:53.591] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 11:57:53.595] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 11:57:53.599] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 11:57:53.605] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 11:57:54.570] [undefined] GET(/:id): Playlist retrieved with id 9 with status 200
[2025-08-15 11:57:59.003] [undefined] DELETE(/:id): Error deleting playlist: update or delete on table "playlists" violates foreign key constraint "playlist_elements_playlist_fkey" on table "playlist_elements" with status 500
[2025-08-15 11:57:59.062] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-15 11:57:59.065] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-15 11:57:59.069] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-15 11:57:59.074] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-15 11:57:59.082] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-15 12:02:47.596] [undefined] POST(/): try to register a user with username: astria and email: sachaguerin.sg@gmail.com
[2025-08-15 12:02:47.647] [undefined] POST(/): successfully registered with status 200
[2025-08-15 12:02:47.659] [undefined] POST(/login): try to login with username 'astria'
[2025-08-15 12:02:47.710] [undefined] POST(/login): Successfully logged in with status 200
[2025-08-15 12:02:49.622] [undefined] GET(/:id/channel): try to retrieve channel of user 1
[2025-08-15 12:02:49.625] [undefined] GET(/:id/channel): failed to retrieve channel of user 1 because it doesn't exist with status 404
[2025-08-15 12:02:49.630] [undefined] GET(/:id/history): try to retrieve history of user 1
[2025-08-15 12:02:49.634] [undefined] GET(/:id/history): failed to retrieve history of user 1 because it doesn't exist with status 404
[2025-08-15 12:02:49.642] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200
[2025-08-15 12:02:56.061] [undefined] POST(/): try to create new channel with owner 1 and name astria
[2025-08-15 12:02:56.063] [undefined] POST(/): Successfully created new channel with name astria with status 200
[2025-08-15 12:02:56.078] [undefined] GET(/:id/channel): try to retrieve channel of user 1
[2025-08-15 12:02:56.082] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200
[2025-08-15 12:02:57.508] [undefined] GET(/:id): try to get channel with id 1
[2025-08-15 12:02:57.519] [undefined] GET(/:id/stats): try to get stats
[2025-08-15 12:02:57.522] [undefined] GET(/:id): Successfully get channel with id 1 with status 200
[2025-08-15 12:02:57.531] [undefined] GET(/:id/stats): Successfully get stats with status 200
[2025-08-15 12:02:58.751] [undefined] GET(/:id/channel): try to retrieve channel of user 1
[2025-08-15 12:02:58.754] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200
[2025-08-15 12:03:17.807] [undefined] POST(/): try to upload video with status undefined
[2025-08-15 12:03:17.812] [undefined] POST(/): successfully uploaded video with status 200
[2025-08-15 12:03:17.878] [undefined] POST(/thumbnail): try to add thumbnail to video 1
[2025-08-15 12:03:17.881] [undefined] POST(/thumbnail): successfully uploaded thumbnail with status 200
[2025-08-15 12:03:17.900] [undefined] PUT(/:id/tags): try to add tags to video 1
[2025-08-15 12:03:17.910] [undefined] PUT(/:id/tags): successfully added tags to video 1 with status 200
[2025-08-15 12:03:21.191] [undefined] GET(/:id): try to get video 1
[2025-08-15 12:03:21.201] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200
[2025-08-15 12:03:21.206] [undefined] GET(/:id): successfully get video 1 with status 200
[2025-08-15 12:03:21.218] [undefined] GET(/:id/similar): try to get similar videos for video 1
[2025-08-15 12:03:21.229] [undefined] GET(/:id/similar): successfully get similar videos for video 1 with status 200
[2025-08-15 12:03:21.250] [undefined] GET(/:id/views): try to add views for video 1
[2025-08-15 12:03:21.265] [undefined] GET(/:id/views): successfully added views for video 1 with status 200
[2025-08-15 12:03:25.914] [undefined] GET(/:id/channel): try to retrieve channel of user 1
[2025-08-15 12:03:25.917] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200
[2025-08-15 12:03:25.919] [undefined] GET(/:id/history): try to retrieve history of user 1
[2025-08-15 12:03:25.925] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200
[2025-08-15 12:03:25.934] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200
[2025-08-15 12:03:30.209] [undefined] POST(/): Playlist created with id 2 with status 200
[2025-08-15 12:03:30.227] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200
[2025-08-15 12:03:34.208] [undefined] GET(/:id): try to get video 1
[2025-08-15 12:03:34.219] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200
[2025-08-15 12:03:34.223] [undefined] GET(/:id): successfully get video 1 with status 200
[2025-08-15 12:03:34.236] [undefined] GET(/:id/similar): try to get similar videos for video 1
[2025-08-15 12:03:34.248] [undefined] GET(/:id/similar): successfully get similar videos for video 1 with status 200
[2025-08-15 12:03:34.273] [undefined] GET(/:id/views): try to add views for video 1
[2025-08-15 12:03:34.281] [undefined] GET(/:id/views): successfully added views for video 1 with status 200
[2025-08-15 12:03:36.394] [undefined] POST(/:id): Video added to playlist with id 2 with status 200
[2025-08-15 12:03:38.143] [undefined] GET(/:id/channel): try to retrieve channel of user 1
[2025-08-15 12:03:38.145] [undefined] GET(/:id/history): try to retrieve history of user 1
[2025-08-15 12:03:38.148] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200
[2025-08-15 12:03:38.151] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200
[2025-08-15 12:03:38.161] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200
[2025-08-15 12:03:38.653] [undefined] GET(/:id): Playlist retrieved with id 2 with status 200
[2025-08-15 12:03:40.880] [undefined] DELETE(/:id): Playlist deleted with status 200
[2025-08-15 12:03:40.925] [undefined] GET(/:id/history): try to retrieve history of user 1
[2025-08-15 12:03:40.928] [undefined] GET(/:id/channel): try to retrieve channel of user 1
[2025-08-15 12:03:40.931] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200
[2025-08-15 12:03:40.933] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200
[2025-08-15 12:03:40.942] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200
[2025-08-15 12:03:52.229] [undefined] POST(/): Playlist created with id 3 with status 200
[2025-08-15 12:03:52.247] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200
[2025-08-15 12:03:53.608] [undefined] GET(/:id): try to get video 1
[2025-08-15 12:03:53.619] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200
[2025-08-15 12:03:53.624] [undefined] GET(/:id): successfully get video 1 with status 200
[2025-08-15 12:03:53.635] [undefined] GET(/:id/similar): try to get similar videos for video 1
[2025-08-15 12:03:53.648] [undefined] GET(/:id/similar): successfully get similar videos for video 1 with status 200
[2025-08-15 12:03:53.675] [undefined] GET(/:id/views): try to add views for video 1
[2025-08-15 12:03:53.685] [undefined] GET(/:id/views): successfully added views for video 1 with status 200
[2025-08-15 12:03:55.180] [undefined] POST(/:id): Video added to playlist with id 3 with status 200
[2025-08-15 12:03:56.494] [undefined] GET(/:id/channel): try to retrieve channel of user 1
[2025-08-15 12:03:56.497] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200
[2025-08-15 12:03:56.500] [undefined] GET(/:id/history): try to retrieve history of user 1
[2025-08-15 12:03:56.504] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200
[2025-08-15 12:03:56.511] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200
[2025-08-15 12:03:57.117] [undefined] GET(/:id): Playlist retrieved with id 3 with status 200
[2025-08-15 12:06:09.157] [undefined] GET(/:id): Playlist retrieved with id 3 with status 200
[2025-08-15 12:06:13.801] [undefined] GET(/:id/channel): try to retrieve channel of user 1
[2025-08-15 12:06:13.805] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200
[2025-08-15 12:06:13.808] [undefined] GET(/:id/history): try to retrieve history of user 1
[2025-08-15 12:06:13.812] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200
[2025-08-15 12:06:13.820] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200
[2025-08-15 12:06:15.043] [undefined] GET(/:id): Playlist retrieved with id 3 with status 200
[2025-08-15 12:07:33.375] [undefined] GET(/:id): Playlist retrieved with id 3 with status 200
[2025-08-15 12:07:46.081] [undefined] GET(/:id): Playlist retrieved with id 3 with status 200
[2025-08-15 12:07:54.278] [undefined] GET(/:id): Playlist retrieved with id 3 with status 200
[2025-08-15 12:08:25.981] [undefined] GET(/:id): Playlist retrieved with id 3 with status 200
[2025-08-15 12:08:48.330] [undefined] GET(/:id): Playlist retrieved with id 3 with status 200
[2025-08-15 12:09:05.838] [undefined] GET(/:id): Playlist retrieved with id 3 with status 200
[2025-08-15 12:09:20.029] [undefined] GET(/:id): Playlist retrieved with id 3 with status 200
[2025-08-15 12:09:31.979] [undefined] GET(/:id): Playlist retrieved with id 3 with status 200
[2025-08-15 12:10:11.328] [undefined] GET(/:id): Playlist retrieved with id 3 with status 200
[2025-08-15 12:10:17.318] [undefined] GET(/:id): Playlist retrieved with id 3 with status 200
[2025-08-15 12:11:07.347] [undefined] GET(/:id): Playlist retrieved with id 3 with status 200
[2025-08-15 12:11:08.287] [undefined] GET(/:id): try to get video 1
[2025-08-15 12:11:08.297] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200
[2025-08-15 12:11:08.302] [undefined] GET(/:id): successfully get video 1 with status 200
[2025-08-15 12:11:08.314] [undefined] GET(/:id/similar): try to get similar videos for video 1
[2025-08-15 12:11:08.327] [undefined] GET(/:id/similar): successfully get similar videos for video 1 with status 200
[2025-08-15 12:11:08.348] [undefined] GET(/:id/views): try to add views for video 1
[2025-08-15 12:11:08.359] [undefined] GET(/:id/views): successfully added views for video 1 with status 200
[2025-08-15 12:11:09.147] [undefined] GET(/:id): Playlist retrieved with id 3 with status 200
[2025-08-15 12:11:43.722] [undefined] GET(/:id): Playlist retrieved with id 3 with status 200
[2025-08-15 12:12:10.236] [undefined] GET(/:id): Playlist retrieved with id 3 with status 200
[2025-08-15 12:12:22.230] [undefined] GET(/:id): Playlist retrieved with id 3 with status 200
[2025-08-15 12:12:36.945] [undefined] GET(/:id): Playlist retrieved with id 3 with status 200
[2025-08-15 12:12:38.251] [undefined] GET(/:id): try to get video 1
[2025-08-15 12:12:38.262] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200
[2025-08-15 12:12:38.266] [undefined] GET(/:id): successfully get video 1 with status 200
[2025-08-15 12:12:38.278] [undefined] GET(/:id/similar): try to get similar videos for video 1
[2025-08-15 12:12:38.291] [undefined] GET(/:id/similar): successfully get similar videos for video 1 with status 200
[2025-08-15 12:12:38.315] [undefined] GET(/:id/views): try to add views for video 1
[2025-08-15 12:12:38.327] [undefined] GET(/:id/views): successfully added views for video 1 with status 200
[2025-08-15 12:12:39.300] [undefined] GET(/:id): Playlist retrieved with id 3 with status 200
[2025-08-15 12:13:16.106] [undefined] GET(/:id): Playlist retrieved with id 3 with status 200
[2025-08-15 12:13:17.470] [undefined] GET(/:id): try to get video 1
[2025-08-15 12:13:17.481] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200
[2025-08-15 12:13:17.487] [undefined] GET(/:id): successfully get video 1 with status 200
[2025-08-15 12:13:17.499] [undefined] GET(/:id/similar): try to get similar videos for video 1
[2025-08-15 12:13:17.513] [undefined] GET(/:id/similar): successfully get similar videos for video 1 with status 200
[2025-08-15 12:13:17.565] [undefined] GET(/:id/views): try to add views for video 1
[2025-08-15 12:13:17.574] [undefined] GET(/:id/views): successfully added views for video 1 with status 200
[2025-08-15 12:13:18.292] [undefined] GET(/:id): Playlist retrieved with id 3 with status 200
[2025-08-15 12:13:19.374] [undefined] GET(/:id): try to get video 1
[2025-08-15 12:13:19.384] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200
[2025-08-15 12:13:19.389] [undefined] GET(/:id): successfully get video 1 with status 200
[2025-08-15 12:13:19.402] [undefined] GET(/:id/similar): try to get similar videos for video 1
[2025-08-15 12:13:19.414] [undefined] GET(/:id/similar): successfully get similar videos for video 1 with status 200
[2025-08-15 12:13:19.438] [undefined] GET(/:id/views): try to add views for video 1
[2025-08-15 12:13:19.446] [undefined] GET(/:id/views): successfully added views for video 1 with status 200
[2025-08-15 12:13:19.797] [undefined] GET(/:id): Playlist retrieved with id 3 with status 200
[2025-08-15 12:13:50.493] [undefined] GET(/:id): Playlist retrieved with id 3 with status 200
[2025-08-15 12:13:52.628] [undefined] GET(/:id): try to get video 1
[2025-08-15 12:13:52.639] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200
[2025-08-15 12:13:52.644] [undefined] GET(/:id): successfully get video 1 with status 200
[2025-08-15 12:13:52.657] [undefined] GET(/:id/similar): try to get similar videos for video 1
[2025-08-15 12:13:52.670] [undefined] GET(/:id/similar): successfully get similar videos for video 1 with status 200
[2025-08-15 12:13:52.693] [undefined] GET(/:id/views): try to add views for video 1
[2025-08-15 12:13:52.705] [undefined] GET(/:id/views): successfully added views for video 1 with status 200
[2025-08-15 12:13:53.217] [undefined] GET(/:id): Playlist retrieved with id 3 with status 200
[2025-08-15 12:16:32.830] [undefined] GET(/:id): Playlist retrieved with id 3 with status 200
[2025-08-15 12:16:33.842] [undefined] GET(/:id): try to get video 1
[2025-08-15 12:16:33.853] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200
[2025-08-15 12:16:33.859] [undefined] GET(/:id): successfully get video 1 with status 200
[2025-08-15 12:16:33.871] [undefined] GET(/:id/similar): try to get similar videos for video 1
[2025-08-15 12:16:33.884] [undefined] GET(/:id/similar): successfully get similar videos for video 1 with status 200
[2025-08-15 12:16:33.909] [undefined] GET(/:id/views): try to add views for video 1
[2025-08-15 12:16:33.917] [undefined] GET(/:id/views): successfully added views for video 1 with status 200
[2025-08-15 12:16:34.233] [undefined] GET(/:id): Playlist retrieved with id 3 with status 200
[2025-08-15 12:18:40.492] [undefined] GET(/:id): Playlist retrieved with id 3 with status 200
[2025-08-15 12:18:51.040] [undefined] GET(/:id): Playlist retrieved with id 3 with status 200
[2025-08-15 12:19:00.143] [undefined] GET(/:id): Playlist retrieved with id 3 with status 200
[2025-08-15 12:19:03.469] [undefined] GET(/:id): Playlist retrieved with id 3 with status 200
[2025-08-15 12:19:55.046] [undefined] GET(/:id): Playlist retrieved with id 3 with status 200
[2025-08-15 12:19:57.124] [undefined] DELETE(/:id/video/:videoId): Video deleted from playlist with id 3 with status 200
[2025-08-15 12:19:57.149] [undefined] GET(/:id): Playlist retrieved with id 3 with status 200
[2025-08-15 12:20:03.498] [undefined] DELETE(/:id): Playlist deleted with status 200
[2025-08-15 12:20:03.611] [undefined] GET(/:id/channel): try to retrieve channel of user 1
[2025-08-15 12:20:03.614] [undefined] GET(/:id/history): try to retrieve history of user 1
[2025-08-15 12:20:03.617] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200
[2025-08-15 12:20:03.621] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200
[2025-08-15 12:20:03.630] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200

1
frontend/src/assets/svg/trash.svg

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M5 20a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8h2V6h-4V4a2 2 0 0 0-2-2H9a2 2 0 0 0-2 2v2H3v2h2zM9 4h6v2H9zM8 8h9v12H7V8z"></path><path d="M9 10h2v8H9zm4 0h2v8h-2z"></path></svg>

After

Width:  |  Height:  |  Size: 260 B

1
frontend/src/components/Navbar.jsx

@ -48,6 +48,7 @@ export default function Navbar({ isSearchPage = false, alerts = [], onCloseAlert
</div> </div>
<div> <div>
<ul className="flex items-center space-x-[44px] font-montserrat text-2xl font-black"> <ul className="flex items-center space-x-[44px] font-montserrat text-2xl font-black">
<li><a href="/">Accueil</a></li>
{isAuthenticated ? ( {isAuthenticated ? (
<> <>
<li><a href="/">Abonnements</a></li> <li><a href="/">Abonnements</a></li>

2
frontend/src/components/PlaylistCard.jsx

@ -4,7 +4,7 @@ export default function PlaylistCard(props){
const {playlist, onClick} = props; const {playlist, onClick} = props;
return ( return (
<div className="glassmorphism w-1/3 p-4 cursor-pointer" onClick={() => {onClick(playlist.id)}}> <div className="glassmorphism p-4 cursor-pointer" onClick={() => {onClick(playlist.id)}}>
<img src={playlist.thumbnail ? playlist.thumbnail : Default} alt={playlist.name} className="rounded-sm" /> <img src={playlist.thumbnail ? playlist.thumbnail : Default} alt={playlist.name} className="rounded-sm" />
<div className="playlist-info"> <div className="playlist-info">
<h3 className="font-montserrat font-semibold text-xl text-white mt-3">{playlist.name}</h3> <h3 className="font-montserrat font-semibold text-xl text-white mt-3">{playlist.name}</h3>

4
frontend/src/components/TrendingVideos.jsx

@ -6,11 +6,9 @@ export default function TrendingVideos({ videos }) {
return ( return (
<div className="mt-10"> <div className="mt-10">
<h2 className="text-3xl font-bold mb-4 text-white">Tendances</h2> <h2 className="text-3xl font-bold mb-4 text-white">Tendances</h2>
<div className="flex flex-wrap gap-11"> <div className="grid grid-cols-5 gap-8 mt-8">
{videos && videos.map((video, index) => ( {videos && videos.map((video, index) => (
<div className="w-445/1920" key={index}>
<VideoCard video={video} key={index} /> <VideoCard video={video} key={index} />
</div>
))} ))}
</div> </div>
</div> </div>

16
frontend/src/components/VideoCard.jsx

@ -25,7 +25,7 @@ import { useNavigate } from 'react-router-dom';
// } // }
// ] // ]
export default function VideoCard({ video }) { export default function VideoCard({ video, showControls = false, onDelete = () => {} }) {
const navigation = useNavigate(); const navigation = useNavigate();
const handleClick = () => { const handleClick = () => {
navigation(`/video/${video.id}`, { navigation(`/video/${video.id}`, {
@ -33,7 +33,8 @@ export default function VideoCard({ video }) {
}) })
} }
return ( return (
<div className="flex flex-col glassmorphism w-full p-6 cursor-pointer" onClick={handleClick} > <div className="flex flex-col glassmorphism w-full p-6 cursor-pointer relative">
<div onClick={handleClick} >
<div className="aspect-video rounded-sm overflow-hidden"> <div className="aspect-video rounded-sm overflow-hidden">
<img <img
src={video.thumbnail} src={video.thumbnail}
@ -48,5 +49,16 @@ export default function VideoCard({ video }) {
<span className="ml-3.5">{video.views} vues</span> <span className="ml-3.5">{video.views} vues</span>
</div> </div>
</div> </div>
{showControls && (
<div className="mt-4">
<button
className="absolute -bottom-5 -right-5 bg-red-500 ml-4 px-3 py-2 rounded-full aspect-square text-white font-montserrat text-lg font-semibold cursor-pointer"
onClick={() => onDelete(video.id)}
>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" className='fill-white' ><path d="M5 20a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8h2V6h-4V4a2 2 0 0 0-2-2H9a2 2 0 0 0-2 2v2H3v2h2zM9 4h6v2H9zM8 8h9v12H7V8z"></path><path d="M9 10h2v8H9zm4 0h2v8h-2z"></path></svg>
</button>
</div>
)}
</div>
); );
} }

27
frontend/src/modals/VerificationModal.jsx

@ -0,0 +1,27 @@
export default function VerificationModal({title, onConfirm, onCancel, isOpen}) {
if (!isOpen) return null;
return (
<div className="fixed inset-0 flex items-center justify-center">
<div className="glassmorphism p-6">
<h2 className="text-lg text-white font-semibold mb-4">{title}</h2>
<div className="flex justify-end">
<button
className="bg-primary px-3 py-2 rounded-sm text-white font-montserrat text-lg font-semibold cursor-pointer"
onClick={() => onConfirm()}
>
Confirmer
</button>
<button
className="bg-red-500 ml-4 px-3 py-2 rounded-sm text-white font-montserrat text-lg font-semibold cursor-pointer"
onClick={() => onCancel()}
>
Annuler
</button>
</div>
</div>
</div>
);
}

12
frontend/src/pages/Account.jsx

@ -86,6 +86,10 @@ export default function Account() {
setIsModalOpen(false); setIsModalOpen(false);
fetchUserChannel(); fetchUserChannel();
} }
const closePlaylistModal = () => {
setIsCreatePlaylistModalOpen(false);
fetchUserPlaylists();
}
return ( return (
<div className="min-w-screen min-h-screen bg-linear-to-br from-left-gradient to-right-gradient"> <div className="min-w-screen min-h-screen bg-linear-to-br from-left-gradient to-right-gradient">
@ -231,7 +235,7 @@ export default function Account() {
Créer une playlist Créer une playlist
</button> </button>
</div> </div>
<div className="w-full mt-5 flex flex-wrap" > <div className="grid grid-cols-3 gap-8 mt-8" >
{ {
userPlaylists && userPlaylists.map((playlist, index) => ( userPlaylists && userPlaylists.map((playlist, index) => (
<PlaylistCard playlist={playlist} key={index} onClick={handlePlaylistClick} /> <PlaylistCard playlist={playlist} key={index} onClick={handlePlaylistClick} />
@ -240,12 +244,10 @@ export default function Account() {
</div> </div>
{/* History */} {/* History */}
<h2 className="font-montserrat font-bold text-3xl text-white mt-10" >Historique</h2> <h2 className="font-montserrat font-bold text-3xl text-white mt-10" >Historique</h2>
<div className="w-full mt-5 flex flex-wrap gap-2" > <div className="grid grid-cols-3 gap-8 mt-8" >
{ {
userHistory && userHistory.map((video, index) => ( userHistory && userHistory.map((video, index) => (
<div className="w-1/3" key={index}>
<VideoCard video={video} /> <VideoCard video={video} />
</div>
)) ))
} }
</div> </div>
@ -253,7 +255,7 @@ export default function Account() {
</main> </main>
<CreateChannelModal isOpen={isModalOpen} onClose={() => closeModal()} addAlert={addAlert} /> <CreateChannelModal isOpen={isModalOpen} onClose={() => closeModal()} addAlert={addAlert} />
<CreatePlaylistModal isOpen={isCreatePlaylistModalOpen} onClose={() => setIsCreatePlaylistModalOpen(false)} addAlert={addAlert} /> <CreatePlaylistModal isOpen={isCreatePlaylistModalOpen} onClose={() => closePlaylistModal()} addAlert={addAlert} />
</div> </div>
) )

97
frontend/src/pages/Playlist.jsx

@ -0,0 +1,97 @@
import { useParams } from "react-router-dom";
import Navbar from "../components/Navbar";
import { useEffect, useState } from "react";
import { getPlaylistById, deletePlaylist, deleteVideo } from "../services/playlist.service.js";
import VideoCard from "../components/VideoCard.jsx";
import VerificationModal from "../modals/VerificationModal.jsx";
import { useNavigate } from "react-router-dom";
export default function Playlist() {
const { id } = useParams();
const navigate = useNavigate();
const [alerts, setAlerts] = useState([]);
const [playlist, setPlaylist] = useState(null);
const [isDeletePlaylistModalOpen, setIsDeletePlaylistModalOpen] = useState(false);
const fetchPlaylistDetails = async () => {
const token = localStorage.getItem("token");
const data = await getPlaylistById(id, token, addAlert);
setPlaylist(data);
}
useEffect(() => {
fetchPlaylistDetails();
}, [id]);
const addAlert = (type, message) => {
const newAlert = { type, message, id: Date.now() }; // Add unique ID
setAlerts([...alerts, newAlert]);
};
const onCloseAlert = (alertToRemove) => {
setAlerts(alerts.filter(alert => alert !== alertToRemove));
};
const onDeletePlaylist = async () => {
const token = localStorage.getItem("token");
await deletePlaylist(id, token, addAlert);
setIsDeletePlaylistModalOpen(false);
navigate("/profile");
}
const onDeleteVideo = async (videoId) => {
const token = localStorage.getItem("token");
await deleteVideo(id, videoId, token, addAlert);
fetchPlaylistDetails();
}
return (
<div className="min-w-screen min-h-screen bg-linear-to-br from-left-gradient to-right-gradient">
<Navbar isSearchPage={false} alerts={alerts} onCloseAlert={onCloseAlert} />
<main className="px-36 w-full pt-[118px]">
<h1 className="font-bold font-montserrat text-3xl text-white" >{playlist && playlist.name}</h1>
{/* CONTROLS */}
<div className="mt-4">
<button
className="bg-primary px-3 py-2 rounded-sm text-white font-montserrat text-lg font-semibold cursor-pointer"
onClick={() => console.log("Modifier playlist")}
>
modifier
</button>
<button
className="bg-red-500 ml-4 px-3 py-2 rounded-sm text-white font-montserrat text-lg font-semibold cursor-pointer"
onClick={() => setIsDeletePlaylistModalOpen(true)}
>
supprimer
</button>
</div>
<div className="grid grid-cols-4 gap-8 mt-12">
{
playlist && playlist.videos && playlist.videos.length > 0 ? playlist.videos.map(video => (
<VideoCard
key={video.id}
video={video}
showControls={true}
onDelete={onDeleteVideo}
/>
)) : (
<p className="text-white">Aucun vidéo trouvée dans cette playlist.</p>
)
}
</div>
</main>
<VerificationModal
title="Confirmer la suppression"
onConfirm={() => onDeletePlaylist()}
onCancel={() => setIsDeletePlaylistModalOpen(false)}
isOpen={isDeletePlaylistModalOpen}
/>
</div>
);
}

61
frontend/src/pages/Video.jsx

@ -8,6 +8,8 @@ import Tag from "../components/Tag.jsx";
import {addView, getSimilarVideos, getVideoById, toggleLike} from "../services/video.service.js"; import {addView, getSimilarVideos, getVideoById, toggleLike} from "../services/video.service.js";
import {subscribe} from "../services/channel.service.js"; import {subscribe} from "../services/channel.service.js";
import {addComment} from "../services/comment.service.js"; import {addComment} from "../services/comment.service.js";
import { getPlaylists } from "../services/user.service.js";
import { addToPlaylist } from "../services/playlist.service.js";
export default function Video() { export default function Video() {
@ -25,6 +27,8 @@ export default function Video() {
const [showControls, setShowControls] = useState(false); const [showControls, setShowControls] = useState(false);
const [comment, setComment] = useState(""); const [comment, setComment] = useState("");
const [alerts, setAlerts] = useState([]); const [alerts, setAlerts] = useState([]);
const [playlists, setPlaylists] = useState([]);
const [isAddToPlaylistOpen, setIsAddToPlaylistOpen] = useState(false);
const fetchVideo = useCallback(async () => { const fetchVideo = useCallback(async () => {
// Fetch video data and similar videos based on the video ID from the URL // Fetch video data and similar videos based on the video ID from the URL
@ -47,8 +51,20 @@ export default function Video() {
await addView(id, addAlert); await addView(id, addAlert);
}, [id, navigation]); }, [id, navigation]);
const fetchPlaylists = async () => {
const token = localStorage.getItem('token');
if (!token) return;
const user = JSON.parse(localStorage.getItem('user'));
const data = await getPlaylists(user.id, token, addAlert);
if (data) {
setPlaylists(data);
}
}
useEffect(() => { useEffect(() => {
fetchVideo(); fetchVideo();
fetchPlaylists();
}, [fetchVideo]); }, [fetchVideo]);
const handlePlayPause = () => { const handlePlayPause = () => {
@ -212,6 +228,22 @@ export default function Video() {
setAlerts(alerts.filter(alert => alert !== alertToRemove)); setAlerts(alerts.filter(alert => alert !== alertToRemove));
}; };
const handleAddToPlaylist = async (id) => {
if (!isAuthenticated) {
navigation('/login');
return;
}
const body = {
video: video.id
}
const token = localStorage.getItem('token');
await addToPlaylist(id, body, token, addAlert);
setIsAddToPlaylistOpen(!isAddToPlaylistOpen);
}
return ( return (
<div className="min-w-screen min-h-screen bg-linear-to-br from-left-gradient to-right-gradient"> <div className="min-w-screen min-h-screen bg-linear-to-br from-left-gradient to-right-gradient">
<Navbar isSearchPage={false} alerts={alerts} onCloseAlert={onCloseAlert} /> <Navbar isSearchPage={false} alerts={alerts} onCloseAlert={onCloseAlert} />
@ -292,6 +324,35 @@ export default function Video() {
</svg> </svg>
</button> </button>
<p className="font-montserrat text-white ml-2" >{video.likes}</p> <p className="font-montserrat text-white ml-2" >{video.likes}</p>
<button className="relative ml-14">
<div className="bg-primary cursor-pointer px-4 py-2 rounded-md flex items-center gap-4" onClick={() => setIsAddToPlaylistOpen(!isAddToPlaylistOpen)} >
<p className="text-white font-montserrat font-bold" >playlist</p>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" className="fill-white"><path d="M19 11h-6V5h-2v6H5v2h6v6h2v-6h6z"></path></svg>
</div>
{
playlists.length > 0 && isAddToPlaylistOpen && (
<div className="absolute inset-0 w-max h-max z-40 glassmorphism top-1/1 mt-2 left-0 rounded-2xl px-4 py-2 cursor-default">
<ul className="flex flex-col gap-2">
{playlists.map((playlist) => (
<li
key={playlist.id}
className="text-white font-montserrat font-medium text-sm cursor-pointer hover:underline flex items-center justify-between gap-4"
onClick={() => handleAddToPlaylist(playlist.id)}
>
<p className="text-start">{playlist.name}</p>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" className="fill-white"><path d="M19 11h-6V5h-2v6H5v2h6v6h2v-6h6z"></path></svg>
</li>
))}
</ul>
</div>
)
}
</button>
</div> </div>
{/* Video details */} {/* Video details */}

9
frontend/src/routes/routes.jsx

@ -9,6 +9,7 @@ import ManageVideo from "../pages/ManageVideo.jsx";
import AddVideo from "../pages/AddVideo.jsx"; import AddVideo from "../pages/AddVideo.jsx";
import Search from "../pages/Search.jsx"; import Search from "../pages/Search.jsx";
import Channel from "../pages/Channel.jsx"; import Channel from "../pages/Channel.jsx";
import Playlist from "../pages/Playlist.jsx";
const routes = [ const routes = [
{ path: "/", element: <Home/> }, { path: "/", element: <Home/> },
@ -79,6 +80,14 @@ const routes = [
element: ( element: (
<Channel/> <Channel/>
) )
},
{
path: "playlist/:id",
element: (
<ProtectedRoute requireAuth={true}>
<Playlist/>
</ProtectedRoute>
)
} }
] ]

81
frontend/src/services/playlist.service.js

@ -21,3 +21,84 @@ export async function createPlaylist(body, token, addAlert) {
addAlert('error', error.message); addAlert('error', error.message);
} }
} }
export async function addToPlaylist(id, body, token, addAlert) {
try {
const response = await fetch(`https://localhost/api/playlists/${id}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
},
body: JSON.stringify(body)
});
if (!response.ok) {
throw new Error('Failed to add video to playlist');
}
const data = await response.json();
addAlert('success', 'Vidéo ajoutée à la playlist avec succès');
return data;
} catch (error) {
addAlert('error', "Erreur lors de l'ajout à la playlist");
}
}
export async function getPlaylistById(id, token, addAlert) {
try {
const response = await fetch(`https://localhost/api/playlists/${id}`, {
headers: {
'Authorization': `Bearer ${token}`
}
});
if (!response.ok) {
throw new Error('Failed to fetch playlist');
}
const data = await response.json();
return data;
} catch (error) {
addAlert('error', error.message);
}
}
export async function deletePlaylist(id, token, addAlert) {
try {
const response = await fetch(`https://localhost/api/playlists/${id}`, {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${token}`
}
});
if (!response.ok) {
throw new Error('Failed to delete playlist');
}
addAlert('success', 'Playlist deleted successfully');
} catch (error) {
addAlert('error', error.message);
}
}
export async function deleteVideo(playlistId, videoId, token, addAlert) {
try {
const response = await fetch(`https://localhost/api/playlists/${playlistId}/video/${videoId}`, {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${token}`
}
});
if (!response.ok) {
throw new Error('Failed to delete video');
}
addAlert('success', 'Video deleted successfully');
} catch (error) {
addAlert('error', error.message);
}
}

Loading…
Cancel
Save