Commit Graph
21 Commits
Author SHA1 Message Date
openhands b058a3827b Fix theme consistency, i18n completeness, CSS variable naming, and hardcoded strings 2026-07-09 18:13:22 +02:00
openhands fc57fb06d1 chore: remove dead code, unused CSS, unused components, and clean up git tracking
- Remove storage/logs/ and prod.log from git tracking; add to .gitignore
- Remove unused AvatarCarousel and ArticleSlider components
- Remove unused SkeletonTable export from ui.tsx
- Remove unused ChevronDown import from admin layout
- Remove 13 unused CSS classes (icon-base, nav-*, navigation-icon*, .app.dark,
  text-body, transition-base, card-base, admin-info-grid, .coin.*)
- Remove duplicate translation keys (openMenu/closeMenu in en.json)
- Fix admin-bans to use Prisma-generated bans_type enum
- Create shared AdminPageHeader component and formatDate utility
- Add logger and generateRequestId for structured logging
- All 58 tests pass, typecheck clean, build succeeds
2026-07-08 13:27:01 +02:00
openhands 25c3040949 Add favicon upload option in admin panel 2026-07-05 23:22:44 +02:00
openhands befa4ec282 Translate admin panel to all 6 languages 2026-07-04 21:21:15 +02:00
remco cf287dbc8b feat: redesign admin panel with Lucide icons and modern styling
- Add lucide-react for SVG icons throughout the admin
- Redesign sidebar with gradient background, icons per nav item, and sticky layout
- Redesign topbar with cleaner user info display
- Redesign dashboard with icon-backed stat cards, gradient progress bars, activity feed
- Update AdminNavLink with icon support and new active state styling
- Improve table styling in admin-page CSS (rounded corners, hover, spacing)
- Clean up unused admin CSS
2026-07-02 15:33:23 +02:00
remco bd299be55d refactor: convert admin panel to Tailwind CSS
- Convert admin layout, sidebar, and navigation to Tailwind classes
- Convert dashboard components (StatusCard, DiagnosticRow, etc.) to Tailwind
- Convert all ~48 admin page files from admin CSS classes to Tailwind
- Remove unused admin CSS from globals.css (973 → 712 lines)
- Convert developers page badges to Tailwind
- Remove <style jsx> block from OnlineUsersWidget
2026-07-02 15:23:07 +02:00
remco c3de7cb576 style: complete housekeeping improvements - online users widget, sidebar cleanup 2026-07-01 18:57:10 +02:00
remco 12576cc113 feat: media library with image picker for article forms, browse/upload from folder 2026-07-01 17:00:35 +02:00
Simo 0cd4d06ff6 Fill the remaining gaps: badge upload, radio tools, VPN, writeable boxes
Built the admin tools previously listed as missing:
- Badge upload (/admin/badges): uploads a <code>.gif into the emulator's
  badge dir via BADGE_UPLOAD_DIR (node:fs); validated code/type/size,
  logged. Made configurable rather than skipped.
- Radio tools: /admin/radio/api-keys (CRUD, server-generated keys),
  /admin/radio/autodj (Auto-DJ playlist CRUD), /admin/radio/embed (embed
  snippet generator), /admin/radio/points (points settings),
  /admin/radio/monitoring (live stream/now-playing/listeners status).
  radio_api_keys + radio_auto_dj_playlist already had real columns.
- /admin/vpn: VPN/proxy detection config (block toggle + provider + key),
  complementing /admin/ip's raw blacklist.
- Writeable boxes: new website_writeable_boxes table (model + migration
  0006) + /admin/writeable-boxes CRUD; active boxes render on the public
  home page. env: BADGE_UPLOAD_DIR.

Verified live (prod, amx_test): all 8 pages render with real data; a test
writeable box appeared on the public home and was reverted. tsc 0,
vitest 49/49, next build 0 (7 new admin routes).
2026-06-28 21:04:34 +02:00
Simo 1199176883 Add Theme Settings tool + polish remaining radio detail pages
- New /admin/theme: recolour the whole site from housekeeping. 6 atom-
  faithful presets (Atom/Midnight/Ocean/Forest/Sunset/Candy) + per-colour
  pickers for the 12 settings ThemeVars injects + border radius. Writes to
  website_settings, busts the siteSettings cache, and revalidates the
  layout so the new palette applies live with no rebuild. Constants live
  in src/lib/theme-presets.ts (a "use server" file can't export objects).
  Added to the admin sidebar (System).
- radio/contests/[id] + giveaways/[id] wrapped in ContentCard to match
  the public design system.
- Skipped a separate VPN page: /admin/ip already manages the IP
  white/blacklist, so it would only duplicate it.

Verified live (prod, amx_test): applied the Ocean preset → home renders
--color-primary #0ea5e9 site-wide; reverted the test rows. tsc 0,
vitest 49/49, next build 0.
2026-06-28 20:20:38 +02:00
Simo f4e0924e71 Restyle the admin panel to match AtomCMS's Filament housekeeping look
The admin pages used bare inline-styled tables on the default page
background. Rebuilt the admin shell + added a scoped .admin CSS layer so
the whole panel matches the original AtomCMS Filament look:
- Dark #2d2d44 sidebar (the AtomCMS admin navbar colour) with the nav
  grouped into Overview / Content / Users & access / Economy / Radio /
  System (mirrors the Filament resource groups), an avatar + rank badge
  header, and amber active-link highlighting via a client AdminNavLink
  (usePathname).
- A topbar ("Housekeeping" + signed-in user) over a light content area.
- Carded tables (surface bg, rounded, shadow, tinted header, row hover)
  and a page-title treatment, applied globally so every admin page is
  styled without per-page edits.

Verified in a real authenticated admin session (production server,
amx_test): sidebar renders #2d2d44 sticky, active link amber on dark
text, /admin/users table carded with 7 real rows; dev server serves the
admin rules after a cache refresh. tsc 0, vitest 49/49, next build 0.
2026-06-28 18:38:54 +02:00
Simo 7daeccb832 Add dark mode, i18n, messenger/moderation/verify, admin CRUD parity
Web-tier features completing the AtomCMS→Next.js conversion (slice 2):

UI/UX:
- Dark mode: html.dark CSS-var overrides + ThemeSwitcher (localStorage,
  no-flash boot script) wired into the nav.
- i18n (next-intl, cookie-based / no URL routing): en + it catalogs,
  request.ts, provider in root layout, LanguageSwitcher; shell (nav,
  header, footer) fully translated. URLs + access-guard unchanged.
- globals.css: --muted/--border aliases used across admin pages.

User features:
- /messages: offline messages + friend-request accept (server action
  re-reads session, two directional rows, idempotent).
- Email verification: signed-token /verify route + sendVerification wired
  into register (best-effort, never blocks signup).
- Article reactions: toggle UI on news/[slug] + server action.
- Content moderation service (website_wordfilter + optional OpenAI
  moderations, fail-open) wired into article comments + guestbook.

Admin CRUD parity (Filament replacement):
- /admin/shop (+ new/[id]) packages CRUD + read-only orders.
- /admin/transactions read-only PayPal log.
- /admin/permissions, /admin/tags, /admin/ads (+ new/[id]),
  /admin/help-questions (+ new/[id]), /admin/radio/history,
  /admin/users/[id]/edit. All gated by requireStaff + logStaffActivity.

Verified: tsc 0, vitest 48/48, next build 0 (all routes incl. new
admin CRUD + /messages + /verify).
2026-06-28 16:06:42 +02:00
Simo 22d53d0e9c Add security middleware, audit log, alerts, PayPal, cron, radio + apps
Security (launch blockers):
- src/middleware.ts (edge): forwards x-pathname + real client IP.
- access-guard.ts (Node, from root layout): routes non-staff to /maintenance
  when maintenance mode is on, banned users to /banned. New /banned + /maintenance
  pages (the consumers the admin toggle was missing). Admin layout enforces
  force_staff_2fa before /admin.
- staff-activity.ts audit log wired into ban/lift/give-currency/set-rank actions.

Infra (parallel agents): alert service (alert_logs + Discord embed + email),
PayPal top-up (create/capture API routes + /shop/topup), cron worker
(scripts/jobs-worker.ts via croner: emulator-ping->alert, maintenance-check,
bans-cleanup), social connections page, admin radio settings/banners/ranks.
Public radio subsystem: /radio (+schedule, shouts+post, contests, giveaways,
apply, leaderboard) and /apply/staff + /apply/team submission forms. Radio nav
link added. .env.example documents the new optional vars.

(radio song-requests dropped: its table is a stub in AtomCMS — columns added by
un-modeled alter-migrations.)

Verified: tsc exit 0, vitest 48/48, next build exit 0 (82 page routes).
2026-06-28 15:10:19 +02:00
Simo e668fa85ec Add 2FA, email + password reset, and batch-7 pages
Auth (hand-built on the auth core):
- 2FA: User model gains two_factor_secret/recovery_codes/confirmed_at (+ idempotent
  MariaDB migration). authorize() requires a valid TOTP code when 2FA is confirmed
  (secret decrypted via Laravel APP_KEY, fail-closed). Two-step login (precheckLogin
  reveals the code field). /settings/2fa enable/confirm/disable flow.
- Password reset: nodemailer email service; PasswordReset model + migration;
  /forgot (request, generic response) + /reset (token sha256 + 1h TTL, sets argon2id
  hash). Login links to forgot.

Batch 7 (parallel agents): /admin/commandocentrum (RCON controls + emulator_errors),
social write actions (friend request + guild forum new thread), /help/[category],
/badges (public). env: APP_KEY, APP_URL, SMTP_*. Nav extended.

Verified: tsc exit 0, vitest 48/48, next build exit 0 (64 page routes).
2026-06-28 14:25:19 +02:00
Simo 486ce51559 Add social login (Discord/Google) + batch-6 pages
Auth: NextAuth Discord + Google providers (enabled when env id+secret set);
OAuth signIn allowed only if a hotel account matches the email; jwt binds the
session to that account (id/rank/username). Login page gets social buttons.

Batch 6 (parallel agents): /friends (messenger_friendships), /guilds/[id]/forum
(threads), /admin/navigation (navigator config), /admin/maintenance (toggle
maintenance settings), /admin/alerts (alert_logs + send hotel alert via RCON).
Header (Friends) + admin nav (Alerts/Maintenance/Navigator) extended.

Verified: tsc exit 0, vitest 48/48, next build exit 0 (57 page routes).
2026-06-28 14:13:41 +02:00
Simo 08a9882be8 Add register + logout auth flows, and batch-5 resources
Auth (hand-built, uses the auth core):
- /register + register() action: validates, hashes with argon2id (hashPassword),
  creates an emulator-compatible users row (accountCreated/ipRegister/ipCurrent/
  look), redirect kept outside try so NEXT_REDIRECT propagates. Login/register
  cross-links; header shows Register (logged-out) and a Logout (signOut) button.

Batch 5 (parallel agents): /admin/rooms (+[id]) search+detail, /admin/vouchers
(CRUD), /admin/subscriptions (read), /admin/calendar (campaigns+rewards read),
/marketplace (public). Header + admin nav extended.

Verified: tsc exit 0, vitest 48/48, next build exit 0 (52 page routes).
2026-06-28 13:52:32 +02:00
Simo e8be0461d8 Add niche admin + public expansions + self-host Nunito font (batches 3-4)
Built via two more parallel agent workflows (read schema -> return files),
integrated + verified.

Admin: /admin/emulator (emulator_settings + emulator_texts key/value editor),
/admin/badges (give-badge via RCON), /admin/rare-values (CRUD), /admin/housekeeping
(CRUD), /admin/email-templates (CRUD), /admin/photos (moderation).
Public: /rares (+[category]), /leaderboard (credits/diamonds/duckets),
/guilds (+[id] members), /redeem (voucher -> sendCurrency).
Expanded: /u/[username] now shows badges + photos + guestbook (post form);
/news/[slug] now shows reactions + comments (comment form). Reactions tallied
in JS (Prisma groupBy typing avoided).
Self-hosted Nunito via next/font/google wired to --font-nunito (the atom theme
font, no runtime external fetch). Header + admin nav extended.

Verified: tsc exit 0, vitest 48/48, next build exit 0.
2026-06-28 13:44:23 +02:00
Simo e96b606e1e Add remaining public + admin pages (parallel build, 26 files)
Built via two parallel agent workflows reading the real Prisma schema, then
integrated + verified.

Public: /shop (categories + storefront), /community hub, /rankings (top by
credits), /staff, /photos (camera_web gallery), /help (categories + rules),
/help/tickets (auth-gated user tickets + create), /settings (auth-gated, update
motto via RCON).

Admin: /admin/catalog (+[id] items), /admin/radio (shouts/apps/schedules +
delete shout), /admin/teams (CRUD), /admin/permissions (read), /admin/wordfilter
(CRUD + RCON push), /admin/ip (whitelist/blacklist CRUD), /admin/applications
(list + dismiss), /admin/logs (chat/command/alert read), /admin/achievements
(read). Server actions all staff-gated.

Header + admin nav extended. Verified: tsc exit 0, vitest 48/48, next build
exit 0 (33 routes); curl-probed every route — public 200/<main>, auth+admin
correctly 307-redirect when unauthorized.
2026-06-28 13:24:55 +02:00
Simo 5f8b465451 Add admin CMS Settings editor (website_settings)
/admin/settings: list all website_settings, inline value edit, add/overwrite,
delete; staff-gated server actions that bust the siteSettings cache after each
write. Admin nav extended (Settings).

Verified: tsc exit 0, vitest 48/48, next build exit 0.
2026-06-28 12:54:18 +02:00
Simo 5861d9f1f5 Add admin Articles (CRUD) + Bans resources
- Articles: list / new / edit / delete (websiteArticles), unique-slug
  generation via slugify() (pure, unit-tested); staff-gated server actions.
- Bans: list active bans (ban_expire > now), create ban (writes the bans row +
  RCON disconnect) with type/duration/reason, lift ban; staff-gated actions.
- Admin nav extended (Articles, Bans).

Verified: tsc exit 0, vitest 48/48, next build exit 0 (7 /admin routes).
2026-06-28 12:52:38 +02:00
Simo 9f81096f05 Add admin foundation + Users resource (Filament replacement, slice 1)
Plain App Router admin (aligned to habbo-next, no Refine):
- rank surfaced on the NextAuth session; staff guard isStaff() [pure,
  unit-tested] + requireStaff() reading min_staff_rank, gating /admin.
- /admin dashboard (counts), /admin/users (paginated + search),
  /admin/users/[id] detail.
- src/actions/admin-users.ts: staff-gated server actions wiring the user editor
  to the existing services — giveCurrency (RCON or DB fallback), setMotto/setRank
  (DB + RCON), alertUser, disconnectUser.

Verified: tsc exit 0, vitest 45/45, next build exit 0 (/admin routes).
2026-06-27 16:51:47 +02:00