feat: add video likes and plays tracking system
Backend (Database & API): - Add likes_count, plays_count, views_count to sexy_videos table - Create sexy_video_likes junction table for user-video likes - Create sexy_video_plays table for analytics tracking - Add POST /sexy/videos/:id/like endpoint - Add DELETE /sexy/videos/:id/like endpoint - Add GET /sexy/videos/:id/like-status endpoint - Add POST /sexy/videos/:id/play endpoint - Add PATCH /sexy/videos/:id/play/:playId endpoint Frontend (Types & Services): - Update Video interface with counter fields - Add VideoLikeStatus, VideoLikeResponse, VideoPlayResponse types - Add likeVideo() service function - Add unlikeVideo() service function - Add getVideoLikeStatus() service function - Add recordVideoPlay() service function - Add updateVideoPlay() service function Next: Implement UI components for like button and play count display
This commit is contained in:
@@ -16,7 +16,7 @@ import {
|
||||
readComments,
|
||||
aggregate,
|
||||
} from "@directus/sdk";
|
||||
import type { Article, Model, Recording, Stats, User, Video } from "$lib/types";
|
||||
import type { Article, Model, Recording, Stats, User, Video, VideoLikeStatus, VideoLikeResponse, VideoPlayResponse } from "$lib/types";
|
||||
import { PUBLIC_URL } from "$env/static/public";
|
||||
import { logger } from "$lib/logger";
|
||||
|
||||
@@ -630,3 +630,95 @@ export async function getRecording(id: string, fetch?: typeof globalThis.fetch)
|
||||
{ id },
|
||||
);
|
||||
}
|
||||
|
||||
export async function likeVideo(videoId: string) {
|
||||
return loggedApiCall(
|
||||
"likeVideo",
|
||||
async () => {
|
||||
const directus = getDirectusInstance(fetch);
|
||||
return directus.request<VideoLikeResponse>(
|
||||
customEndpoint({
|
||||
method: "POST",
|
||||
path: `/sexy/videos/${videoId}/like`,
|
||||
})
|
||||
);
|
||||
},
|
||||
{ videoId }
|
||||
);
|
||||
}
|
||||
|
||||
export async function unlikeVideo(videoId: string) {
|
||||
return loggedApiCall(
|
||||
"unlikeVideo",
|
||||
async () => {
|
||||
const directus = getDirectusInstance(fetch);
|
||||
return directus.request<VideoLikeResponse>(
|
||||
customEndpoint({
|
||||
method: "DELETE",
|
||||
path: `/sexy/videos/${videoId}/like`,
|
||||
})
|
||||
);
|
||||
},
|
||||
{ videoId }
|
||||
);
|
||||
}
|
||||
|
||||
export async function getVideoLikeStatus(videoId: string, fetch?: typeof globalThis.fetch) {
|
||||
return loggedApiCall(
|
||||
"getVideoLikeStatus",
|
||||
async () => {
|
||||
const directus = getDirectusInstance(fetch);
|
||||
return directus.request<VideoLikeStatus>(
|
||||
customEndpoint({
|
||||
method: "GET",
|
||||
path: `/sexy/videos/${videoId}/like-status`,
|
||||
})
|
||||
);
|
||||
},
|
||||
{ videoId }
|
||||
);
|
||||
}
|
||||
|
||||
export async function recordVideoPlay(videoId: string, sessionId?: string) {
|
||||
return loggedApiCall(
|
||||
"recordVideoPlay",
|
||||
async () => {
|
||||
const directus = getDirectusInstance(fetch);
|
||||
return directus.request<VideoPlayResponse>(
|
||||
customEndpoint({
|
||||
method: "POST",
|
||||
path: `/sexy/videos/${videoId}/play`,
|
||||
body: JSON.stringify({ session_id: sessionId }),
|
||||
headers: { "Content-Type": "application/json" },
|
||||
})
|
||||
);
|
||||
},
|
||||
{ videoId }
|
||||
);
|
||||
}
|
||||
|
||||
export async function updateVideoPlay(
|
||||
videoId: string,
|
||||
playId: string,
|
||||
durationWatched: number,
|
||||
completed: boolean
|
||||
) {
|
||||
return loggedApiCall(
|
||||
"updateVideoPlay",
|
||||
async () => {
|
||||
const directus = getDirectusInstance(fetch);
|
||||
return directus.request(
|
||||
customEndpoint({
|
||||
method: "PATCH",
|
||||
path: `/sexy/videos/${videoId}/play/${playId}`,
|
||||
body: JSON.stringify({
|
||||
duration_watched: durationWatched,
|
||||
completed,
|
||||
}),
|
||||
headers: { "Content-Type": "application/json" },
|
||||
})
|
||||
);
|
||||
},
|
||||
{ videoId, playId, durationWatched, completed }
|
||||
);
|
||||
}
|
||||
|
||||
@@ -89,6 +89,9 @@ export interface Video {
|
||||
upload_date: Date;
|
||||
premium?: boolean;
|
||||
featured?: boolean;
|
||||
likes_count?: number;
|
||||
plays_count?: number;
|
||||
views_count?: number;
|
||||
}
|
||||
|
||||
export interface Comment {
|
||||
@@ -155,3 +158,25 @@ export interface Recording {
|
||||
featured?: boolean;
|
||||
public?: boolean;
|
||||
}
|
||||
|
||||
export interface VideoLikeStatus {
|
||||
liked: boolean;
|
||||
}
|
||||
|
||||
export interface VideoPlayRecord {
|
||||
id: string;
|
||||
video_id: string;
|
||||
duration_watched?: number;
|
||||
completed: boolean;
|
||||
}
|
||||
|
||||
export interface VideoLikeResponse {
|
||||
liked: boolean;
|
||||
likes_count: number;
|
||||
}
|
||||
|
||||
export interface VideoPlayResponse {
|
||||
success: boolean;
|
||||
play_id: string;
|
||||
plays_count: number;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user