Add map community reactions, comments, and moderation
Some checks failed
Deploy MineGeo to Dokploy / deploy (push) Failing after 3m22s
Some checks failed
Deploy MineGeo to Dokploy / deploy (push) Failing after 3m22s
This commit is contained in:
89
shared/community.ts
Normal file
89
shared/community.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
import { z } from "zod";
|
||||
import type { ProfileAppearance } from "./profile-appearance";
|
||||
|
||||
export const communityCategories = {
|
||||
spam: "Spam",
|
||||
advertising: "Advertising",
|
||||
inappropriate: "Inappropriate content",
|
||||
harassment: "Harassment",
|
||||
other: "Other",
|
||||
} as const;
|
||||
export const reactionInput = z
|
||||
.object({ value: z.union([z.literal(-1), z.literal(0), z.literal(1)]) })
|
||||
.strict();
|
||||
export const commentInput = z
|
||||
.object({ body: z.string().trim().min(1).max(2000) })
|
||||
.strict();
|
||||
export const communityReportInput = z.discriminatedUnion("target", [
|
||||
z
|
||||
.object({
|
||||
target: z.literal("comment"),
|
||||
targetId: z.string().uuid(),
|
||||
category: z.enum(
|
||||
Object.keys(communityCategories) as [
|
||||
keyof typeof communityCategories,
|
||||
...Array<keyof typeof communityCategories>,
|
||||
],
|
||||
),
|
||||
reason: z.string().trim().min(10).max(2000),
|
||||
})
|
||||
.strict(),
|
||||
z
|
||||
.object({
|
||||
target: z.literal("account"),
|
||||
targetId: z.string().uuid(),
|
||||
category: z.enum(
|
||||
Object.keys(communityCategories) as [
|
||||
keyof typeof communityCategories,
|
||||
...Array<keyof typeof communityCategories>,
|
||||
],
|
||||
),
|
||||
reason: z.string().trim().min(10).max(2000),
|
||||
})
|
||||
.strict(),
|
||||
]);
|
||||
export const communityReviewInput = z
|
||||
.object({
|
||||
decision: z.enum(["resolved", "dismissed"]),
|
||||
reason: z.string().trim().min(10).max(2000),
|
||||
})
|
||||
.strict();
|
||||
export type MapCommentRecord = {
|
||||
id: string;
|
||||
dataset_id: string;
|
||||
author_id: string | null;
|
||||
body: string;
|
||||
created_at: string;
|
||||
removed_at: string | null;
|
||||
removed_by: string | null;
|
||||
};
|
||||
export type CommunityReportRecord = {
|
||||
id: string;
|
||||
reporter_id: string | null;
|
||||
target: "comment" | "account";
|
||||
comment_id: string | null;
|
||||
account_id: string | null;
|
||||
category: keyof typeof communityCategories;
|
||||
reason: string;
|
||||
state: "open" | "resolved" | "dismissed";
|
||||
reviewer_id: string | null;
|
||||
reviewed_at: string | null;
|
||||
review_reason: string | null;
|
||||
created_at: string;
|
||||
};
|
||||
export type CommunityComment = Pick<
|
||||
MapCommentRecord,
|
||||
"id" | "body" | "created_at" | "author_id"
|
||||
> & { author: string; appearance?: ProfileAppearance };
|
||||
export type MapCommunityView = {
|
||||
likes: number;
|
||||
dislikes: number;
|
||||
reaction: number;
|
||||
viewer: { id: string; canModerate: boolean } | null;
|
||||
comments: CommunityComment[];
|
||||
nextCursor: string | null;
|
||||
};
|
||||
export type CommunityReportView = CommunityReportRecord & {
|
||||
comment: MapCommentRecord | null;
|
||||
accountName: string | null;
|
||||
};
|
||||
@@ -62,6 +62,42 @@ export type Database = {
|
||||
};
|
||||
public: {
|
||||
Tables: {
|
||||
map_reactions: {
|
||||
Row: {
|
||||
dataset_id: string;
|
||||
user_id: string;
|
||||
value: number;
|
||||
created_at: string;
|
||||
};
|
||||
Insert: {
|
||||
dataset_id: string;
|
||||
user_id: string;
|
||||
value: number;
|
||||
created_at?: string;
|
||||
};
|
||||
Update: { value?: number };
|
||||
Relationships: [];
|
||||
};
|
||||
map_comments: {
|
||||
Row: import("./community").MapCommentRecord;
|
||||
Insert: Partial<import("./community").MapCommentRecord> &
|
||||
Pick<
|
||||
import("./community").MapCommentRecord,
|
||||
"dataset_id" | "author_id" | "body"
|
||||
>;
|
||||
Update: Partial<import("./community").MapCommentRecord>;
|
||||
Relationships: [];
|
||||
};
|
||||
community_reports: {
|
||||
Row: import("./community").CommunityReportRecord;
|
||||
Insert: Partial<import("./community").CommunityReportRecord> &
|
||||
Pick<
|
||||
import("./community").CommunityReportRecord,
|
||||
"reporter_id" | "target" | "category" | "reason"
|
||||
>;
|
||||
Update: Partial<import("./community").CommunityReportRecord>;
|
||||
Relationships: [];
|
||||
};
|
||||
account_appeals: {
|
||||
Row: AccountAppealRecord;
|
||||
Insert: Partial<AccountAppealRecord> &
|
||||
@@ -782,6 +818,10 @@ export type Database = {
|
||||
[_ in never]: never;
|
||||
};
|
||||
Functions: {
|
||||
map_reaction_summary: {
|
||||
Args: { p_dataset: string };
|
||||
Returns: { likes: number; dislikes: number }[];
|
||||
};
|
||||
admin_account_action: {
|
||||
Args: {
|
||||
p_reviewer: string;
|
||||
|
||||
@@ -1,4 +1,37 @@
|
||||
{
|
||||
"Deleted player": "Удалённый игрок",
|
||||
"Open map": "Открыть карту",
|
||||
"Account ID:": "ID аккаунта:",
|
||||
"Map community": "Сообщество карты",
|
||||
"Map reactions": "Оценки карты",
|
||||
"Like": "Нравится",
|
||||
"Dislike": "Не нравится",
|
||||
"Comments": "Комментарии",
|
||||
"Loading comments…": "Загрузка комментариев…",
|
||||
"Sign in to react, comment, or report.": "Войдите, чтобы оценивать карты, писать комментарии и отправлять жалобы.",
|
||||
"Write a comment": "Написать комментарий",
|
||||
"Share your thoughts about this map.": "Поделитесь впечатлениями об этой карте.",
|
||||
"Publish comment": "Опубликовать комментарий",
|
||||
"Comment published.": "Комментарий опубликован.",
|
||||
"Comment removed.": "Комментарий удалён.",
|
||||
"No comments yet. Be the first to share your thoughts.": "Комментариев пока нет. Поделитесь впечатлениями первым.",
|
||||
"Remove comment": "Удалить комментарий",
|
||||
"Load more comments": "Загрузить ещё комментарии",
|
||||
"Report comment": "Пожаловаться на комментарий",
|
||||
"Report account": "Пожаловаться на аккаунт",
|
||||
"Reported comment": "Жалоба на комментарий",
|
||||
"Reported account": "Жалоба на аккаунт",
|
||||
"Spam": "Спам",
|
||||
"Advertising": "Реклама",
|
||||
"Inappropriate content": "Недопустимое содержимое",
|
||||
"Harassment": "Травля и оскорбления",
|
||||
"Report sent for moderator review.": "Жалоба отправлена модератору.",
|
||||
"A moderator will review your report. Reports do not automatically remove content or ban accounts.": "Модератор рассмотрит жалобу. Жалобы не приводят к автоматическому удалению содержимого или блокировке аккаунтов.",
|
||||
"Comment and account reports": "Жалобы на комментарии и аккаунты",
|
||||
"Review the evidence before taking action. Resolving a report does not automatically ban an account or remove a comment.": "Проверьте обстоятельства перед принятием мер. Закрытие жалобы не блокирует аккаунт и не удаляет комментарий автоматически.",
|
||||
"No open comment or account reports.": "Открытых жалоб на комментарии и аккаунты нет.",
|
||||
"Resolve report": "Закрыть жалобу",
|
||||
"Load more reports": "Загрузить ещё жалобы",
|
||||
"Forum": "Форум",
|
||||
"Site language": "Язык сайта",
|
||||
"Automatic": "Автоматически",
|
||||
|
||||
Reference in New Issue
Block a user