Add map community reactions, comments, and moderation
Some checks failed
Deploy MineGeo to Dokploy / deploy (push) Failing after 3m22s

This commit is contained in:
2026-10-17 12:45:18 +05:00
parent 0bd05d6e0b
commit e1a6ab5730
17 changed files with 1747 additions and 0 deletions

89
shared/community.ts Normal file
View 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;
};

View File

@@ -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;

View File

@@ -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": "Автоматически",