99 lines
2.6 KiB
TypeScript
99 lines
2.6 KiB
TypeScript
|
|
import type Database from 'better-sqlite3';
|
||
|
|
|
||
|
|
export type WishlistEntry = {
|
||
|
|
recipe_id: number;
|
||
|
|
title: string;
|
||
|
|
image_path: string | null;
|
||
|
|
source_domain: string | null;
|
||
|
|
added_by_profile_id: number | null;
|
||
|
|
added_by_name: string | null;
|
||
|
|
added_at: string;
|
||
|
|
like_count: number;
|
||
|
|
liked_by_me: 0 | 1;
|
||
|
|
avg_stars: number | null;
|
||
|
|
};
|
||
|
|
|
||
|
|
export type SortKey = 'popular' | 'newest' | 'oldest';
|
||
|
|
|
||
|
|
export function listWishlist(
|
||
|
|
db: Database.Database,
|
||
|
|
activeProfileId: number | null,
|
||
|
|
sort: SortKey = 'popular'
|
||
|
|
): WishlistEntry[] {
|
||
|
|
const orderBy = {
|
||
|
|
popular: 'like_count DESC, w.added_at DESC',
|
||
|
|
newest: 'w.added_at DESC',
|
||
|
|
oldest: 'w.added_at ASC'
|
||
|
|
}[sort];
|
||
|
|
|
||
|
|
return db
|
||
|
|
.prepare(
|
||
|
|
`SELECT
|
||
|
|
w.recipe_id,
|
||
|
|
r.title,
|
||
|
|
r.image_path,
|
||
|
|
r.source_domain,
|
||
|
|
w.added_by_profile_id,
|
||
|
|
p.name AS added_by_name,
|
||
|
|
w.added_at,
|
||
|
|
(SELECT COUNT(*) FROM wishlist_like wl WHERE wl.recipe_id = w.recipe_id) AS like_count,
|
||
|
|
CASE
|
||
|
|
WHEN ? IS NULL THEN 0
|
||
|
|
WHEN EXISTS (SELECT 1 FROM wishlist_like wl
|
||
|
|
WHERE wl.recipe_id = w.recipe_id AND wl.profile_id = ?)
|
||
|
|
THEN 1
|
||
|
|
ELSE 0
|
||
|
|
END AS liked_by_me,
|
||
|
|
(SELECT AVG(stars) FROM rating WHERE recipe_id = w.recipe_id) AS avg_stars
|
||
|
|
FROM wishlist w
|
||
|
|
JOIN recipe r ON r.id = w.recipe_id
|
||
|
|
LEFT JOIN profile p ON p.id = w.added_by_profile_id
|
||
|
|
ORDER BY ${orderBy}`
|
||
|
|
)
|
||
|
|
.all(activeProfileId, activeProfileId) as WishlistEntry[];
|
||
|
|
}
|
||
|
|
|
||
|
|
export function isOnWishlist(db: Database.Database, recipeId: number): boolean {
|
||
|
|
return (
|
||
|
|
db
|
||
|
|
.prepare('SELECT 1 AS ok FROM wishlist WHERE recipe_id = ?')
|
||
|
|
.get(recipeId) !== undefined
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
export function addToWishlist(
|
||
|
|
db: Database.Database,
|
||
|
|
recipeId: number,
|
||
|
|
profileId: number | null
|
||
|
|
): void {
|
||
|
|
db.prepare(
|
||
|
|
`INSERT INTO wishlist(recipe_id, added_by_profile_id)
|
||
|
|
VALUES (?, ?)
|
||
|
|
ON CONFLICT(recipe_id) DO NOTHING`
|
||
|
|
).run(recipeId, profileId);
|
||
|
|
}
|
||
|
|
|
||
|
|
export function removeFromWishlist(db: Database.Database, recipeId: number): void {
|
||
|
|
db.prepare('DELETE FROM wishlist WHERE recipe_id = ?').run(recipeId);
|
||
|
|
}
|
||
|
|
|
||
|
|
export function likeWish(
|
||
|
|
db: Database.Database,
|
||
|
|
recipeId: number,
|
||
|
|
profileId: number
|
||
|
|
): void {
|
||
|
|
db.prepare(
|
||
|
|
'INSERT OR IGNORE INTO wishlist_like(recipe_id, profile_id) VALUES (?, ?)'
|
||
|
|
).run(recipeId, profileId);
|
||
|
|
}
|
||
|
|
|
||
|
|
export function unlikeWish(
|
||
|
|
db: Database.Database,
|
||
|
|
recipeId: number,
|
||
|
|
profileId: number
|
||
|
|
): void {
|
||
|
|
db.prepare(
|
||
|
|
'DELETE FROM wishlist_like WHERE recipe_id = ? AND profile_id = ?'
|
||
|
|
).run(recipeId, profileId);
|
||
|
|
}
|