Reconcile website_* schema to the live AtomCMS DB (amx_test)

Introspected the live DB and fixed real drift between the hand-modeled
schema and the actual columns:
- Added missing @map("snake_case") on camelCase fields that silently
  failed at query time: website_teams (rank_name/hidden_rank/...),
  website_paypal_transactions/user_guestbooks/help_center_tickets(+replies)/
  used_shop_vouchers/maintenance_tasks (user_id), website_rare_values
  (currency_type).
- website_permissions was modeled as key/value/comment but is actually
  permission/min_rank/description — fixed the model + the admin page/action.
- website_shop_articles.icon -> icon_url (+ added category_id, is_giftable);
  updated the shop page + admin shop CRUD.
- website_shop_categories: dropped non-existent slug/timestamps, added the
  real description/order columns; updated the shop page.
- website_shop_article_features.features(Json) -> content(Text).

Verified against amx_test: all website_* query errors gone; home renders
the real hotel_name ("Habbo"), rankings shows real users, /staff + /shop
200. tsc 0, vitest 49/49, next build 0. Remaining missing tables
(radio_*/game_*/staff_activities/alert_logs/article_comments+reactions)
don't exist in this DB and degrade gracefully via try/catch.
This commit is contained in:
Simo committed 2026-06-28 16:35:27 +02:00
1 parent 4eccd146ba
commit b97a88c561
6 files changed
+92 -93

No files matched your search

+5 -6
View File
@@ -15,7 +15,7 @@ type ShopArticle = {
id: bigint;
name: string;
info: string;
icon: string;
iconUrl: string;
color: string;
costs: number;
credits: number | null;
@@ -28,7 +28,6 @@ type ShopArticle = {
type ShopCategory = {
id: bigint;
name: string;
slug: string;
icon: string | null;
};
@@ -36,7 +35,7 @@ const ARTICLE_SELECT = {
id: true,
name: true,
info: true,
icon: true,
iconUrl: true,
color: true,
costs: true,
credits: true,
@@ -59,7 +58,7 @@ export default async function ShopPage({
let categories: ShopCategory[] = [];
try {
categories = await prisma.websiteShopCategories.findMany({
select: { id: true, name: true, slug: true, icon: true },
select: { id: true, name: true, icon: true },
orderBy: { name: "asc" },
});
} catch {
@@ -169,12 +168,12 @@ export default async function ShopPage({
overflow: "hidden",
}}
>
{a.icon ? (
{a.iconUrl ? (
// Article icons are arbitrary external/Imgur URLs from the
// emulator data, so a plain <img> is correct here.
// eslint-disable-next-line @next/next/no-img-element
<img
src={a.icon}
src={a.iconUrl}
alt=""
width={48}
height={48}