Test / lib /feedback-service.ts
TrikozikGames's picture
Add source files
eddc354
Raw
History Blame Contribute Delete
1.81 kB
/**
* Обратная связь от пользователей («чего не хватает»).
* Сейчас всё хранится в localStorage.
* SUPABASE: заменить на таблицу `feedback` (insert для user, select для admin).
*/
export type FeedbackItem = {
id: string;
userId: string;
username: string;
text: string;
createdAt: number;
read: boolean;
};
export const FEEDBACK_KEY = "realknot-feedback-v1";
const safe = <T,>(fn: () => T, fallback: T): T => {
try {
return fn();
} catch {
return fallback;
}
};
const newId = () => Math.random().toString(36).slice(2, 10);
/** SUPABASE: `supabase.from("feedback").select("*").order("created_at")`. */
export const listFeedback = (): FeedbackItem[] =>
safe(() => {
const raw = localStorage.getItem(FEEDBACK_KEY);
const arr = raw ? (JSON.parse(raw) as FeedbackItem[]) : [];
return arr.sort((a, b) => b.createdAt - a.createdAt);
}, []);
const write = (list: FeedbackItem[]) =>
safe(() => localStorage.setItem(FEEDBACK_KEY, JSON.stringify(list)), undefined);
/** SUPABASE: `supabase.from("feedback").insert({ ... })`. */
export const addFeedback = (userId: string, username: string, text: string) => {
const item: FeedbackItem = {
id: newId(),
userId,
username,
text: text.trim(),
createdAt: Date.now(),
read: false,
};
write([item, ...listFeedback()]);
return item;
};
export const markFeedbackRead = (id: string) => {
write(listFeedback().map((f) => (f.id === id ? { ...f, read: true } : f)));
return listFeedback();
};
export const removeFeedback = (id: string) => {
write(listFeedback().filter((f) => f.id !== id));
return listFeedback();
};
export const unreadFeedbackCount = () => listFeedback().filter((f) => !f.read).length;