astro_avtourist/frontend/src/lib/pb.ts

188 lines
5.2 KiB
TypeScript
Raw Normal View History

import PocketBase from 'pocketbase';
import type { Post } from '../globalInterfaces';
const PB_URL = import.meta.env.PB_POCKETBASE_URL || 'http://127.0.0.1:8090';
export const pb = new PocketBase(PB_URL);
if (typeof window !== 'undefined') {
const token = localStorage.getItem('auth_token');
const userStr = localStorage.getItem('user');
// Инициализируем куку из localStorage если её нет
if (token && !document.cookie.includes('pb_auth')) {
document.cookie = `pb_auth=${token}; path=/; max-age=${7 * 24 * 60 * 60}; SameSite=Lax`;
}
if (token && userStr) {
try {
const user = JSON.parse(userStr);
pb.authStore.save(token, user);
} catch (e) {
console.error('Failed to restore auth:', e);
}
}
}
export interface PostVotes {
id: string;
post_id: string;
user_id: string;
vote_type: 'like' | 'dislike';
created: string;
updated: string;
}
export interface VoteStats {
likes: number;
dislikes: number;
userVote: 'like' | 'dislike' | null;
}
export async function getPostVotes(postId: string): Promise<VoteStats> {
const votes = await pb.collection('post_votes').getList(1, 1000, {
filter: `post_id="${postId}"`,
});
const likes = votes.items.filter((v) => v.vote_type === 'like').length;
const dislikes = votes.items.filter((v) => v.vote_type === 'dislike').length;
let userVote: 'like' | 'dislike' | null = null;
if (pb.authStore.isValid) {
const userId = pb.authStore.model?.id;
const userVoteRecord = votes.items.find((v) => v.user_id === userId);
if (userVoteRecord) {
userVote = userVoteRecord.vote_type as 'like' | 'dislike';
}
}
return { likes, dislikes, userVote };
}
export async function getPostVotesStats(postId: string): Promise<{ likes: number; dislikes: number }> {
// Получаем данные из коллекции голосов
const votes = await pb.collection('post_votes').getList(1, 1000, {
filter: `post="${postId}"`,
});
const likes = votes.items.filter((v: any) => v.vote_type === 'like').length;
const dislikes = votes.items.filter((v: any) => v.vote_type === 'dislike').length;
return { likes, dislikes };
}
export async function vote(postId: string, voteType: 'like' | 'dislike'): Promise<VoteStats> {
const userId = pb.authStore.model?.id;
if (!userId) {
throw new Error('Требуется авторизация');
}
const existingVotes = await pb.collection('post_votes').getList(1, 1, {
filter: `post_id="${postId}" && user_id="${userId}"`,
});
if (existingVotes.items.length > 0) {
const existingVote = existingVotes.items[0] as unknown as PostVotes;
if (existingVote.vote_type === voteType) {
await pb.collection('post_votes').delete(existingVote.id);
} else {
await pb.collection('post_votes').update(existingVote.id, {
vote_type: voteType,
});
}
} else {
await pb.collection('post_votes').create({
post_id: postId,
user_id: userId,
vote_type: voteType,
});
}
return getPostVotes(postId);
}
export async function getPosts(options?: {
page?: number;
perPage?: number;
category?: string;
search?: string;
}): Promise<{ posts: Post[]; total: number; page: number; totalPages: number }> {
const page = options?.page || 1;
const perPage = options?.perPage || 10;
const filter: string[] = ['draft = false'];
if (options?.category && options.category !== 'Все') {
filter.push(`category = "${options.category}"`);
}
if (options?.search) {
filter.push(`(title ~ "${options.search}" || description ~ "${options.search}")`);
}
const result = await pb.collection('posts').getList(page, perPage, {
filter: filter.join(' && '),
sort: '-date',
});
return {
posts: (result.items || []) as unknown as Post[],
total: result.totalItems || 0,
page: result.page || 1,
totalPages: result.totalPages || 1,
};
}
export async function getPostBySlug(slug: string): Promise<Post | null> {
const result = await pb.collection('posts').getList(1, 1, {
filter: `slug="${slug}" && draft = false`,
});
if (!result.items || result.totalItems === 0) {
return null;
}
return result.items[0] as unknown as Post;
}
export const FIXED_BLOG_CATEGORIES = [
'ДТП',
'Лишение прав',
'Страховые споры',
'Штрафы ГИБДД',
'Возмещение ущерба',
'Судебные дела',
];
export async function getAllCategories(): Promise<string[]> {
return ['Все', ...FIXED_BLOG_CATEGORIES];
}
export function getPostImageUrl(post: { image?: string }): string {
if (post.image) {
const fileUrl = pb.files.getUrl(post, post.image);
if (fileUrl.startsWith('/')) {
return `${PB_URL}${fileUrl}`;
}
return fileUrl;
}
return '/images/blog/default.avif';
}
export async function getPostViews(postId: string): Promise<number> {
try {
const post = await pb.collection('posts').getOne(postId);
return post.views || 0;
} catch {
return 0;
}
}
export async function incrementPostViews(postId: string): Promise<number> {
const post = await pb.collection('posts').getOne(postId);
const newViews = (post.views || 0) + 1;
await pb.collection('posts').update(postId, { views: newViews });
return newViews;
}