Fix theme consistency, i18n completeness, CSS variable naming, and hardcoded strings
This commit is contained in:
1 parent
0abd490f67
commit
b058a3827b
37 files changed
+431
-214
No files matched your search
@@ -72,7 +72,7 @@ export default async function AdminApplications() {
|
||||
{applications.length === 0 ? (
|
||||
<div className="admin-empty">{t("noApplications")}</div>
|
||||
) : (
|
||||
<div className="grid cols-2">
|
||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
{applications.map((a) => {
|
||||
const username = userMap.get(a.userId);
|
||||
return (
|
||||
|
||||
@@ -137,7 +137,7 @@ export default async function AdminCalendarCampaign({
|
||||
</thead>
|
||||
<tbody>
|
||||
{rewards.map((r) => (
|
||||
<tr key={r.id} className="border-t border-[var(--border)]">
|
||||
<tr key={r.id} className="border-t border-[var(--border-subtle)]">
|
||||
<td>{r.id}</td>
|
||||
<td>{r.productName || <span className="text-sm text-gray-500 dark:text-gray-400">—</span>}</td>
|
||||
<td className="text-sm text-gray-500 dark:text-gray-400 whitespace-nowrap">{r.itemId > 0 ? r.itemId : "—"}</td>
|
||||
|
||||
@@ -83,7 +83,7 @@ export default async function AdminCalendar() {
|
||||
{campaigns.length === 0 ? (
|
||||
<div className="admin-empty">{t("noCampaigns")}</div>
|
||||
) : (
|
||||
<div className="grid cols-3">
|
||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-3">
|
||||
{campaigns.map((c) => {
|
||||
const enabled = c.enabled === "1";
|
||||
const count = rewardCounts.get(c.id) ?? 0;
|
||||
|
||||
@@ -122,7 +122,7 @@ export default async function AdminCatalogPage({
|
||||
</thead>
|
||||
<tbody>
|
||||
{items.map((it) => (
|
||||
<tr key={it.id} style={{ borderTop: "1px solid var(--border)" }}>
|
||||
<tr key={it.id} style={{ borderTop: "1px solid var(--border-subtle)" }}>
|
||||
<td>{it.id}</td>
|
||||
<td>
|
||||
{it.catalogName}
|
||||
|
||||
@@ -141,7 +141,7 @@ export default async function CommandoCentrum() {
|
||||
</section>
|
||||
|
||||
{/* ── Server info + diagnostics ──────────────────────────── */}
|
||||
<div className="grid cols-2">
|
||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
<section className="admin-card p-5">
|
||||
<h2 className="admin-section-title">{t("serverInfo")}</h2>
|
||||
<div className="grid grid-cols-[repeat(auto-fit,minmax(150px,1fr))] gap-2.5">
|
||||
|
||||
@@ -73,7 +73,7 @@ export function FaviconForm({ currentUrl }: { currentUrl: string | null }) {
|
||||
<img
|
||||
src={preview}
|
||||
alt="Favicon preview"
|
||||
className="w-16 h-16 rounded-lg border-2 border-[var(--border)] object-contain bg-white"
|
||||
className="w-16 h-16 rounded-lg border-2 border-[var(--border-subtle)] object-contain bg-white"
|
||||
/>
|
||||
<div className="text-xs text-[var(--color-text-muted)] break-all">{preview}</div>
|
||||
</div>
|
||||
|
||||
@@ -85,7 +85,7 @@ export function FaviconGenerator({ onSave }: Props) {
|
||||
ref={canvasRef}
|
||||
width={SIZE}
|
||||
height={SIZE}
|
||||
className="border-2 border-[var(--border)] rounded-xl shadow-lg"
|
||||
className="border-2 border-[var(--border-subtle)] rounded-xl shadow-lg"
|
||||
style={{ width: 128, height: 128, imageRendering: "pixelated" }}
|
||||
/>
|
||||
</div>
|
||||
@@ -114,7 +114,7 @@ export function FaviconGenerator({ onSave }: Props) {
|
||||
type="color"
|
||||
value={bgColor}
|
||||
onChange={(e) => setBgColor(e.target.value)}
|
||||
className="w-10 h-10 rounded-lg cursor-pointer border border-[var(--border)]"
|
||||
className="w-10 h-10 rounded-lg cursor-pointer border border-[var(--border-subtle)]"
|
||||
/>
|
||||
<span className="text-xs text-[var(--color-text-muted)] font-mono">{bgColor}</span>
|
||||
</div>
|
||||
@@ -142,7 +142,7 @@ export function FaviconGenerator({ onSave }: Props) {
|
||||
type="color"
|
||||
value={textColor}
|
||||
onChange={(e) => setTextColor(e.target.value)}
|
||||
className="w-10 h-10 rounded-lg cursor-pointer border border-[var(--border)]"
|
||||
className="w-10 h-10 rounded-lg cursor-pointer border border-[var(--border-subtle)]"
|
||||
/>
|
||||
<span className="text-xs text-[var(--color-text-muted)] font-mono">{textColor}</span>
|
||||
</div>
|
||||
|
||||
@@ -72,7 +72,7 @@ export default async function AdminIp() {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="grid cols-2">
|
||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
{/* ── Whitelist ──────────────────── */}
|
||||
<section className="mt-6">
|
||||
<h2 className="admin-section-title">{t("whitelist")}</h2>
|
||||
|
||||
@@ -163,10 +163,10 @@ async function Topbar({ staff }: { staff: { id: number; username: string; rank:
|
||||
const t = await getTranslations("pages.admin.nav");
|
||||
|
||||
return (
|
||||
<header className="flex items-center justify-between gap-4 bg-[var(--color-surface)] border border-[var(--border)] rounded-2xl px-5 py-3 mb-5 shadow-card">
|
||||
<header className="flex items-center justify-between gap-4 bg-[var(--color-surface)] border border-[var(--border-subtle)] rounded-2xl px-5 py-3 mb-5 shadow-card">
|
||||
<div className="flex items-center gap-3">
|
||||
<h2 className="m-0 text-base font-extrabold text-[var(--color-text)]">{t("housekeeping")}</h2>
|
||||
<span className="hidden sm:inline-block w-px h-5 bg-[var(--border)]" />
|
||||
<span className="hidden sm:inline-block w-px h-5 bg-[var(--border-subtle)]" />
|
||||
<span className="hidden sm:inline text-xs text-[var(--color-text-muted)]">
|
||||
{t("hotelManagementPanel")}
|
||||
</span>
|
||||
|
||||
@@ -103,7 +103,7 @@ export default async function AdminDashboard() {
|
||||
) : (
|
||||
<div className="space-y-0">
|
||||
{activity.map((a, i) => (
|
||||
<div key={String(a.id)} className={`flex items-center gap-3 py-2.5 ${i > 0 ? "border-t border-[var(--border)]" : ""}`}>
|
||||
<div key={String(a.id)} className={`flex items-center gap-3 py-2.5 ${i > 0 ? "border-t border-[var(--border-subtle)]" : ""}`}>
|
||||
<div className="w-7 h-7 rounded-full bg-[var(--color-primary)]/10 grid place-items-center flex-none">
|
||||
<Activity size={12} className="text-[var(--color-primary)]" />
|
||||
</div>
|
||||
|
||||
@@ -44,7 +44,7 @@ export default async function AdminPhotos() {
|
||||
{photos.length === 0 ? (
|
||||
<div className="admin-empty">{t("noPhotos")}</div>
|
||||
) : (
|
||||
<div className="grid cols-3">
|
||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-3">
|
||||
{photos.map((p) => (
|
||||
<div key={String(p.id)} className="admin-card" style={{ padding: 0, overflow: "hidden" }}>
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
|
||||
@@ -119,7 +119,7 @@ export default async function AdminRadioApiKeysPage() {
|
||||
{t("apiKeysForm.generateHint")}
|
||||
</p>
|
||||
<form action={createApiKey} className="admin-card">
|
||||
<div className="grid cols-2">
|
||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
<div>
|
||||
<label htmlFor="new_name" style={{ display: "block", fontWeight: 700 }}>
|
||||
{t("apiKeysForm.name")}
|
||||
|
||||
@@ -118,7 +118,7 @@ export default async function AdminRadioAutoDjPage() {
|
||||
<section className="mt-6">
|
||||
<h2 className="admin-section-title">{t("autoDjForm.addTrack")}</h2>
|
||||
<form action={createTrack} className="admin-card">
|
||||
<div className="grid cols-2">
|
||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
<div>
|
||||
<label htmlFor="new_title" style={{ display: 'block', fontWeight: 700 }}>
|
||||
{t("autoDjForm.title")}
|
||||
|
||||
@@ -101,7 +101,7 @@ export default async function AdminRadioBannersPage() {
|
||||
<section className="mt-6">
|
||||
<h2 className="admin-section-title">{t("banners.addBanner")}</h2>
|
||||
<form action={createRadioBanner} className="admin-card">
|
||||
<div className="grid cols-2">
|
||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
<div>
|
||||
<label htmlFor="new_imagePath" style={{ display: 'block', fontWeight: 700 }}>
|
||||
{t("banners.form.imagePath")}
|
||||
@@ -185,7 +185,7 @@ export default async function AdminRadioBannersPage() {
|
||||
|
||||
<form action={updateRadioBanner}>
|
||||
<input type="hidden" name="id" value={String(b.id)} />
|
||||
<div className="grid cols-2">
|
||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
<div>
|
||||
<label
|
||||
htmlFor={`img_${b.id}`}
|
||||
|
||||
@@ -108,7 +108,7 @@ export default async function AdminRadioPointsPage({
|
||||
<section className="mt-6">
|
||||
<h2 className="admin-section-title">{t("pointsForm.settings")}</h2>
|
||||
<form action={savePoints}>
|
||||
<div className="grid cols-2">
|
||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
<div>
|
||||
<label htmlFor="radio_points_enabled" style={{ display: "block", fontWeight: 700 }}>
|
||||
{t("pointsForm.pointsEnabled")}
|
||||
|
||||
@@ -84,7 +84,7 @@ export default async function AdminRadioRanksPage() {
|
||||
<section className="mt-6">
|
||||
<h2 className="admin-section-title">{t("ranksForm.addRank")}</h2>
|
||||
<form action={createRadioRank} className="admin-card">
|
||||
<div className="grid cols-3">
|
||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-3">
|
||||
<div>
|
||||
<label htmlFor="new_name" style={{ display: 'block', fontWeight: 700 }}>
|
||||
{t("ranksForm.name")}
|
||||
|
||||
@@ -279,7 +279,7 @@ export default async function AdminRadioSettingsPage() {
|
||||
{groups.map((group) => (
|
||||
<section key={group.title} className="admin-card" style={{ marginBottom: '1.25rem' }}>
|
||||
<h2 style={{ marginTop: 0 }}>{group.title}</h2>
|
||||
<div className="grid cols-2">
|
||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
{group.fields.map((field) => (
|
||||
<div key={field.key}>
|
||||
<label
|
||||
|
||||
@@ -83,7 +83,7 @@ export default async function AdminTagsPage() {
|
||||
|
||||
<form action={createTag} className="admin-card mb-6">
|
||||
<h3 style={{ marginTop: 0 }}>{t("addTag")}</h3>
|
||||
<div className="grid cols-2">
|
||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
<div>
|
||||
<label htmlFor="new_name" style={{ display: 'block', fontWeight: 700 }}>
|
||||
{t("name")}
|
||||
|
||||
@@ -62,7 +62,7 @@ export default async function AdminTeams() {
|
||||
<div className="admin-card" style={{ marginBottom: "1.5rem" }}>
|
||||
<h3 style={{ marginTop: 0 }}>{t("newTeamRank")}</h3>
|
||||
<form action={createTeam} style={{ display: "grid", gap: "0.6rem" }}>
|
||||
<div className="grid cols-2">
|
||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
<label style={{ display: "grid", gap: "0.25rem" }}>
|
||||
<span className="text-sm text-gray-500 dark:text-gray-400">{t("rankName")}</span>
|
||||
<input name="rankName" placeholder={t("rankNamePlaceholder")} required />
|
||||
|
||||
@@ -96,7 +96,7 @@ export default async function AdminUserEdit({
|
||||
<form action={updateUser} className="admin-card">
|
||||
<input type="hidden" name="id" value={user.id} />
|
||||
|
||||
<div className="grid cols-2">
|
||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
<label>
|
||||
{t("email")}
|
||||
<input name="mail" type="email" defaultValue={user.mail ?? ""} maxLength={500} />
|
||||
|
||||
@@ -79,7 +79,7 @@ export default async function AdminUserDetail({
|
||||
|
||||
<section className="mt-6">
|
||||
<h2 className="admin-section-title">{t("detail.actions")}</h2>
|
||||
<div className="grid cols-2">
|
||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
<form action={giveCurrency} className="admin-card">
|
||||
<input type="hidden" name="userId" value={user.id} />
|
||||
<h3 className="text-sm font-bold text-[var(--color-text)] m-0 mb-3">{t("detail.giveCurrency")}</h3>
|
||||
|
||||
@@ -92,7 +92,7 @@ export default async function AdminVouchers() {
|
||||
|
||||
<form action={createVoucher} className="admin-card mb-6">
|
||||
<h3 style={{ marginTop: 0 }}>{t("newVoucher")}</h3>
|
||||
<div className="grid cols-2" style={{ marginBottom: "0.75rem" }}>
|
||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-2" style={{ marginBottom: "0.75rem" }}>
|
||||
<label style={{ display: "flex", flexDirection: "column", gap: "0.3rem" }}>
|
||||
<span className="text-sm text-gray-500 dark:text-gray-400">{t("form.code")}</span>
|
||||
<input name="code" placeholder={t("form.codePlaceholder")} maxLength={255} required />
|
||||
|
||||
@@ -80,7 +80,7 @@ export default async function AdminVpn({
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div className="grid cols-2">
|
||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
<div>
|
||||
<label
|
||||
htmlFor="vpn_provider"
|
||||
|
||||
@@ -47,7 +47,7 @@ export default async function AdminWriteableBoxes() {
|
||||
|
||||
<section className="mt-6">
|
||||
<h2 className="admin-section-title">{t("newBox")}</h2>
|
||||
<form action={createBox} className="grid cols-2">
|
||||
<form action={createBox} className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
<div>
|
||||
<label htmlFor="new_title" style={{ display: "block", fontWeight: 700 }}>
|
||||
{t("form.name")}
|
||||
@@ -127,7 +127,7 @@ export default async function AdminWriteableBoxes() {
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<form action={updateBox} className="grid cols-2">
|
||||
<form action={updateBox} className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
<input type="hidden" name="id" value={String(box.id)} />
|
||||
<div>
|
||||
<label
|
||||
|
||||
Reference in new issue
Block a user