Polish content pages: share AuthTopBar, page-grid helper and responsive tables
- Extract shared AuthTopBar frosted top bar; reuse in login & register - Add .page-grid class replacing 48 inline grid styles - Add .table-scroll + .table-cell-truncate helpers; wrap leaderboard/staff tables - Constrain settings page width (max-w-5xl) and stack profile card on mobile - Use theme background var for shop category icon (dark-mode safe)
This commit is contained in:
1 parent
d4677972cd
commit
b57697b2e0
50 files changed
+243
-260
No files matched your search
@@ -96,7 +96,7 @@ export default async function ApplyStaffPage({
|
|||||||
const appliedRankIds = new Set(myApps.map((a) => a.rankId));
|
const appliedRankIds = new Set(myApps.map((a) => a.rankId));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
{submitted === "1" ? (
|
{submitted === "1" ? (
|
||||||
<div role="status" style={feedbackStyle("success")}>
|
<div role="status" style={feedbackStyle("success")}>
|
||||||
{t("success.submitted")}
|
{t("success.submitted")}
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ export default async function ApplyTeamPage({
|
|||||||
const appliedTeamIds = new Set(myApps.map((a) => a.rankId));
|
const appliedTeamIds = new Set(myApps.map((a) => a.rankId));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
{submitted === "1" ? (
|
{submitted === "1" ? (
|
||||||
<div role="status" style={feedbackStyle("success")}>
|
<div role="status" style={feedbackStyle("success")}>
|
||||||
{t("success.submitted")}
|
{t("success.submitted")}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export default async function BadgesPage() {
|
|||||||
.catch(() => []);
|
.catch(() => []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
<ContentCard icon="🏅" title={t("title")} subtitle={t("subtitle")} />
|
<ContentCard icon="🏅" title={t("title")} subtitle={t("subtitle")} />
|
||||||
|
|
||||||
<ContentCard padded={badges.length === 0}>
|
<ContentCard padded={badges.length === 0}>
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ export default function CommunityPage() {
|
|||||||
const t = useTranslations("pages.community");
|
const t = useTranslations("pages.community");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
<ContentCard icon="🌍" title={t("title")} subtitle={t("subtitle")} />
|
<ContentCard icon="🌍" title={t("title")} subtitle={t("subtitle")} />
|
||||||
|
|
||||||
<div className="card-grid sm-2 lg-3">
|
<div className="card-grid sm-2 lg-3">
|
||||||
|
|||||||
@@ -389,7 +389,7 @@ export default function DevelopersPage() {
|
|||||||
const totalEndpoints = GROUPS.reduce((n, g) => n + g.endpoints.length, 0);
|
const totalEndpoints = GROUPS.reduce((n, g) => n + g.endpoints.length, 0);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
<ContentCard
|
<ContentCard
|
||||||
icon="🧩"
|
icon="🧩"
|
||||||
title="Developer API"
|
title="Developer API"
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ export default async function DrawBadgePage({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
<ContentCard
|
<ContentCard
|
||||||
icon="🎨"
|
icon="🎨"
|
||||||
title="Draw a Badge"
|
title="Draw a Badge"
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ export default async function EventDetailPage({
|
|||||||
else if (isFull) disabledReason = t("eventFull");
|
else if (isFull) disabledReason = t("eventFull");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
<p className="muted" style={{ margin: 0 }}>
|
<p className="muted" style={{ margin: 0 }}>
|
||||||
<Link href="/events">{t("back")}</Link>
|
<Link href="/events">{t("back")}</Link>
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ export default async function EventsPage() {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
<ContentCard icon="📅" title={t("title")} subtitle={t("subtitle")} />
|
<ContentCard icon="📅" title={t("title")} subtitle={t("subtitle")} />
|
||||||
|
|
||||||
<ContentCard padded={events.length === 0}>
|
<ContentCard padded={events.length === 0}>
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ export default async function FriendsPage({
|
|||||||
: null;
|
: null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
{removed === "1" ? (
|
{removed === "1" ? (
|
||||||
<div role="status" style={feedbackStyle("success")}>
|
<div role="status" style={feedbackStyle("success")}>
|
||||||
{t("success.removed")}
|
{t("success.removed")}
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ export default async function GuildForumThreadPage({
|
|||||||
: null;
|
: null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
{replied === "1" ? (
|
{replied === "1" ? (
|
||||||
<div role="status" style={feedbackStyle("success")}>
|
<div role="status" style={feedbackStyle("success")}>
|
||||||
{t("success.replied")}
|
{t("success.replied")}
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ export default async function NewThreadPage({
|
|||||||
: null;
|
: null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
{errorMessage ? (
|
{errorMessage ? (
|
||||||
<div role="alert" style={feedbackStyle("error")}>
|
<div role="alert" style={feedbackStyle("error")}>
|
||||||
{errorMessage}
|
{errorMessage}
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ export default async function GuildForumPage({
|
|||||||
const usernameById = new Map(users.map((u) => [u.id, u.username]));
|
const usernameById = new Map(users.map((u) => [u.id, u.username]));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
{posted === "1" ? (
|
{posted === "1" ? (
|
||||||
<div role="status" style={feedbackStyle("success")}>
|
<div role="status" style={feedbackStyle("success")}>
|
||||||
{t("success.posted")}
|
{t("success.posted")}
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ export default async function GuildPage({
|
|||||||
const created = formatDate(new Date(guild.dateCreated * 1000), "date");
|
const created = formatDate(new Date(guild.dateCreated * 1000), "date");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
<p style={{ margin: 0 }}>
|
<p style={{ margin: 0 }}>
|
||||||
<Link href="/guilds">{t("allGuilds")}</Link>
|
<Link href="/guilds">{t("allGuilds")}</Link>
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ export default async function GuildsPage() {
|
|||||||
const guilds = await getGuilds();
|
const guilds = await getGuilds();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
<ContentCard icon="🚪" title={t("title")} subtitle={t("subtitle")} />
|
<ContentCard icon="🚪" title={t("title")} subtitle={t("subtitle")} />
|
||||||
|
|
||||||
<ContentCard padded={guilds.length === 0}>
|
<ContentCard padded={guilds.length === 0}>
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ export default async function HelpCategoryPage({
|
|||||||
const hasButton = Boolean(cat.buttonText && cat.buttonText.trim() !== "");
|
const hasButton = Boolean(cat.buttonText && cat.buttonText.trim() !== "");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
<p style={{ margin: 0 }}>
|
<p style={{ margin: 0 }}>
|
||||||
<Link href="/help">{t("back")}</Link>
|
<Link href="/help">{t("back")}</Link>
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ export default async function HelpCenterPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
<ContentCard
|
<ContentCard
|
||||||
icon="❓"
|
icon="❓"
|
||||||
title={t("title")}
|
title={t("title")}
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ export default async function HelpTicketDetailPage({
|
|||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
{replied === "1" ? (
|
{replied === "1" ? (
|
||||||
<div role="status" style={feedbackStyle("success")}>
|
<div role="status" style={feedbackStyle("success")}>
|
||||||
{t("success.replied")}
|
{t("success.replied")}
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ export default async function HelpTicketsPage({
|
|||||||
: null;
|
: null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
{created === "1" ? (
|
{created === "1" ? (
|
||||||
<div role="status" style={feedbackStyle("success")}>
|
<div role="status" style={feedbackStyle("success")}>
|
||||||
{t("success.created")}
|
{t("success.created")}
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ export default async function LeaderboardPage({
|
|||||||
: null;
|
: null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
<ContentCard
|
<ContentCard
|
||||||
icon="📊"
|
icon="📊"
|
||||||
title={t("title")}
|
title={t("title")}
|
||||||
@@ -165,58 +165,60 @@ export default async function LeaderboardPage({
|
|||||||
{rows.length === 0 ? (
|
{rows.length === 0 ? (
|
||||||
<EmptyState icon="📊">{t("emptyState")}</EmptyState>
|
<EmptyState icon="📊">{t("emptyState")}</EmptyState>
|
||||||
) : (
|
) : (
|
||||||
<table>
|
<div className="table-scroll">
|
||||||
<thead>
|
<table>
|
||||||
<tr>
|
<thead>
|
||||||
<th style={{ width: "3rem" }}>#</th>
|
<tr>
|
||||||
<th style={{ width: "3.5rem" }}>{t("colAvatar")}</th>
|
<th style={{ width: "3rem" }}>#</th>
|
||||||
<th>{t("colPlayer")}</th>
|
<th style={{ width: "3.5rem" }}>{t("colAvatar")}</th>
|
||||||
<th style={{ textAlign: "right" }}>{t(`tab_${active}`)}</th>
|
<th>{t("colPlayer")}</th>
|
||||||
</tr>
|
<th style={{ textAlign: "right" }}>{t(`tab_${active}`)}</th>
|
||||||
</thead>
|
</tr>
|
||||||
<tbody>
|
</thead>
|
||||||
{rows.map((row, i) => {
|
<tbody>
|
||||||
return (
|
{rows.map((row, i) => {
|
||||||
<tr key={row.username}>
|
return (
|
||||||
<td>
|
<tr key={row.username}>
|
||||||
<RankBadge position={i + 1} />
|
<td>
|
||||||
</td>
|
<RankBadge position={i + 1} />
|
||||||
<td>
|
</td>
|
||||||
<UserAvatarThumbnail
|
<td>
|
||||||
figure={row.look}
|
<UserAvatarThumbnail
|
||||||
alt={`${row.username} avatar`}
|
figure={row.look}
|
||||||
/>
|
alt={`${row.username} avatar`}
|
||||||
</td>
|
/>
|
||||||
<td>
|
</td>
|
||||||
<Link
|
<td>
|
||||||
href={`/u/${encodeURIComponent(row.username)}`}
|
<Link
|
||||||
style={{ fontWeight: 700 }}
|
href={`/u/${encodeURIComponent(row.username)}`}
|
||||||
>
|
style={{ fontWeight: 700 }}
|
||||||
{row.username}
|
|
||||||
</Link>
|
|
||||||
</td>
|
|
||||||
<td style={{ textAlign: "right" }}>
|
|
||||||
{activeCurrency ? (
|
|
||||||
<span
|
|
||||||
className="currency"
|
|
||||||
style={{ display: "inline-flex" }}
|
|
||||||
>
|
>
|
||||||
<CurrencyIcon
|
{row.username}
|
||||||
kind={activeCurrency}
|
</Link>
|
||||||
size={22}
|
</td>
|
||||||
alt=""
|
<td style={{ textAlign: "right" }}>
|
||||||
/>
|
{activeCurrency ? (
|
||||||
{row.value.toLocaleString()}
|
<span
|
||||||
</span>
|
className="currency"
|
||||||
) : (
|
style={{ display: "inline-flex" }}
|
||||||
<strong>{formatValue(active, row.value)}</strong>
|
>
|
||||||
)}
|
<CurrencyIcon
|
||||||
</td>
|
kind={activeCurrency}
|
||||||
</tr>
|
size={22}
|
||||||
);
|
alt=""
|
||||||
})}
|
/>
|
||||||
</tbody>
|
{row.value.toLocaleString()}
|
||||||
</table>
|
</span>
|
||||||
|
) : (
|
||||||
|
<strong>{formatValue(active, row.value)}</strong>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</ContentCard>
|
</ContentCard>
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
@@ -2,14 +2,12 @@ import { count, desc, eq } from "drizzle-orm";
|
|||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { getTranslations } from "next-intl/server";
|
import { getTranslations } from "next-intl/server";
|
||||||
|
import { AuthTopBar } from "@/components/auth/auth-top-bar";
|
||||||
import { LoginForm } from "@/components/auth/login-form";
|
import { LoginForm } from "@/components/auth/login-form";
|
||||||
import { Clock } from "@/components/clock";
|
|
||||||
import { LanguageSwitcher } from "@/components/language-switcher";
|
|
||||||
import Link from "@/components/link";
|
import Link from "@/components/link";
|
||||||
import { Reveal } from "@/components/motion-reveal";
|
import { Reveal } from "@/components/motion-reveal";
|
||||||
import { UserAvatarThumbnail } from "@/components/shared/user-avatar-thumbnail";
|
import { UserAvatarThumbnail } from "@/components/shared/user-avatar-thumbnail";
|
||||||
import { SurfaceCard } from "@/components/surface-card";
|
import { SurfaceCard } from "@/components/surface-card";
|
||||||
import { ThemeSwitcher } from "@/components/theme-switcher";
|
|
||||||
import { cached } from "@/lib/cache";
|
import { cached } from "@/lib/cache";
|
||||||
import { db, User } from "@/lib/db";
|
import { db, User } from "@/lib/db";
|
||||||
import { resolveHotelName } from "@/lib/hotel-name";
|
import { resolveHotelName } from "@/lib/hotel-name";
|
||||||
@@ -50,74 +48,7 @@ export default async function LoginPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx-auto w-full max-w-6xl flex flex-col gap-8 pb-16">
|
<div className="mx-auto w-full max-w-6xl flex flex-col gap-8 pb-16">
|
||||||
{/* ── Top Bar ── */}
|
<AuthTopBar hotelName={hotelName} logo={logo} />
|
||||||
<Reveal>
|
|
||||||
<div
|
|
||||||
className="relative flex items-center justify-between rounded-xl border px-5 py-3"
|
|
||||||
style={{
|
|
||||||
background:
|
|
||||||
"color-mix(in srgb, var(--color-surface) 60%, transparent)",
|
|
||||||
backdropFilter: "blur(14px)",
|
|
||||||
WebkitBackdropFilter: "blur(14px)",
|
|
||||||
borderColor:
|
|
||||||
"color-mix(in srgb, var(--color-text-muted) 8%, transparent)",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div className="flex items-center gap-3">
|
|
||||||
{logo ? (
|
|
||||||
<Image
|
|
||||||
src={logo}
|
|
||||||
alt={hotelName}
|
|
||||||
width={100}
|
|
||||||
height={28}
|
|
||||||
className="shrink-0 object-contain"
|
|
||||||
unoptimized
|
|
||||||
style={{ maxHeight: 28, width: "auto", height: "auto" }}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<Image
|
|
||||||
src="/assets/images/icons/lighthouse.png"
|
|
||||||
alt={hotelName}
|
|
||||||
width={28}
|
|
||||||
height={28}
|
|
||||||
className="shrink-0"
|
|
||||||
unoptimized
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<span
|
|
||||||
className="text-sm font-extrabold uppercase tracking-wide"
|
|
||||||
style={{ color: "var(--color-text-readable)" }}
|
|
||||||
>
|
|
||||||
{hotelName}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="flex items-center gap-1.5 rounded-lg px-2 py-1"
|
|
||||||
style={{
|
|
||||||
background:
|
|
||||||
"color-mix(in srgb, var(--color-text-muted) 4%, transparent)",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<LanguageSwitcher />
|
|
||||||
<div
|
|
||||||
className="w-px h-5"
|
|
||||||
style={{
|
|
||||||
background:
|
|
||||||
"color-mix(in srgb, var(--color-text-muted) 12%, transparent)",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Clock />
|
|
||||||
<div
|
|
||||||
className="w-px h-5"
|
|
||||||
style={{
|
|
||||||
background:
|
|
||||||
"color-mix(in srgb, var(--color-text-muted) 12%, transparent)",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<ThemeSwitcher />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Reveal>
|
|
||||||
|
|
||||||
<Reveal>
|
<Reveal>
|
||||||
<div className="flex flex-col gap-8 lg:flex-row">
|
<div className="flex flex-col gap-8 lg:flex-row">
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ export default async function MarketplacePage() {
|
|||||||
const total = offers.reduce((sum, o) => sum + o.price, 0);
|
const total = offers.reduce((sum, o) => sum + o.price, 0);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
<ContentCard icon="🛍️" title={t("title")} subtitle={t("subtitle")}>
|
<ContentCard icon="🛍️" title={t("title")} subtitle={t("subtitle")}>
|
||||||
<div className="stat-grid">
|
<div className="stat-grid">
|
||||||
<StatBlock
|
<StatBlock
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ export default async function MessagesPage({
|
|||||||
: null;
|
: null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
{accepted === "1" ? (
|
{accepted === "1" ? (
|
||||||
<div role="status" style={feedbackStyle("success")}>
|
<div role="status" style={feedbackStyle("success")}>
|
||||||
{t("success.accepted")}
|
{t("success.accepted")}
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ export default async function ArticlePage({
|
|||||||
: null;
|
: null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
{comment === "posted" ? (
|
{comment === "posted" ? (
|
||||||
<div role="status" style={feedbackStyle("success")}>
|
<div role="status" style={feedbackStyle("success")}>
|
||||||
{t("success.posted")}
|
{t("success.posted")}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export default async function NewsPage() {
|
|||||||
const articles = await getNewsList(30);
|
const articles = await getNewsList(30);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
<ContentCard icon="📰" title={t("title")} subtitle={t("subtitle")} />
|
<ContentCard icon="📰" title={t("title")} subtitle={t("subtitle")} />
|
||||||
|
|
||||||
<ContentCard padded={articles.length === 0}>
|
<ContentCard padded={articles.length === 0}>
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ export default async function PhotosPage() {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
<ContentCard icon="📸" title={t("title")} subtitle={t("subtitle")} />
|
<ContentCard icon="📸" title={t("title")} subtitle={t("subtitle")} />
|
||||||
|
|
||||||
<ContentCard padded={items.length === 0}>
|
<ContentCard padded={items.length === 0}>
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ export default async function PollDetailPage({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
<p className="muted" style={{ margin: 0 }}>
|
<p className="muted" style={{ margin: 0 }}>
|
||||||
<Link href="/polls">{t("back")}</Link>
|
<Link href="/polls">{t("back")}</Link>
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ export default async function PollsPage() {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
<ContentCard icon="📊" title={t("title")} subtitle={t("subtitle")} />
|
<ContentCard icon="📊" title={t("title")} subtitle={t("subtitle")} />
|
||||||
|
|
||||||
<ContentCard padded={polls.length === 0}>
|
<ContentCard padded={polls.length === 0}>
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ export default async function RadioApplyPage({
|
|||||||
: null;
|
: null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
{submitted === "1" ? (
|
{submitted === "1" ? (
|
||||||
<div role="status" style={feedbackStyle("success")}>
|
<div role="status" style={feedbackStyle("success")}>
|
||||||
{t("success.submitted")}
|
{t("success.submitted")}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ export default async function RadioContestDetailPage({
|
|||||||
const active = contest.isActive ? "Active" : "Ended";
|
const active = contest.isActive ? "Active" : "Ended";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
<p className="muted" style={{ margin: 0 }}>
|
<p className="muted" style={{ margin: 0 }}>
|
||||||
<Link href="/radio/contests">← Back to contests</Link>
|
<Link href="/radio/contests">← Back to contests</Link>
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export default async function RadioContestsPage() {
|
|||||||
.catch(() => []);
|
.catch(() => []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
<ContentCard icon="🎉" title={t("title")} subtitle={t("subtitle")} />
|
<ContentCard icon="🎉" title={t("title")} subtitle={t("subtitle")} />
|
||||||
|
|
||||||
<ContentCard padded={contests.length === 0}>
|
<ContentCard padded={contests.length === 0}>
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ export default async function RadioGiveawayDetailPage({
|
|||||||
: null);
|
: null);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
<p className="muted" style={{ margin: 0 }}>
|
<p className="muted" style={{ margin: 0 }}>
|
||||||
<Link href="/radio/giveaways">← Back to giveaways</Link>
|
<Link href="/radio/giveaways">← Back to giveaways</Link>
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export default async function RadioGiveawaysPage() {
|
|||||||
.catch(() => []);
|
.catch(() => []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
<ContentCard icon="🎁" title={t("title")} subtitle={t("subtitle")} />
|
<ContentCard icon="🎁" title={t("title")} subtitle={t("subtitle")} />
|
||||||
|
|
||||||
<ContentCard padded={giveaways.length === 0}>
|
<ContentCard padded={giveaways.length === 0}>
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ export default async function RadioLeaderboardPage() {
|
|||||||
const rows = await loadRows();
|
const rows = await loadRows();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
<ContentCard icon="🏆" title={t("title")} subtitle={t("subtitle")} />
|
<ContentCard icon="🏆" title={t("title")} subtitle={t("subtitle")} />
|
||||||
|
|
||||||
<ContentCard padded={rows.length === 0}>
|
<ContentCard padded={rows.length === 0}>
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ export default async function RadioPage() {
|
|||||||
const isLive = Boolean(streamUrl);
|
const isLive = Boolean(streamUrl);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
{/* ── Header: live stream + now playing ─────────────────────── */}
|
{/* ── Header: live stream + now playing ─────────────────────── */}
|
||||||
<ContentCard
|
<ContentCard
|
||||||
icon="📻"
|
icon="📻"
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ export default async function RadioSchedulePage() {
|
|||||||
const hasAny = schedules.length > 0;
|
const hasAny = schedules.length > 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
<ContentCard icon="🗓️" title={t("title")} subtitle={t("subtitle")} />
|
<ContentCard icon="🗓️" title={t("title")} subtitle={t("subtitle")} />
|
||||||
|
|
||||||
<ContentCard padded={!hasAny}>
|
<ContentCard padded={!hasAny}>
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ export default async function RadioShoutsPage({
|
|||||||
: null;
|
: null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
{posted === "1" ? (
|
{posted === "1" ? (
|
||||||
<div role="status" style={feedbackStyle("success")}>
|
<div role="status" style={feedbackStyle("success")}>
|
||||||
{t("success.posted")}
|
{t("success.posted")}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export default async function RankingsPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
<ContentCard icon="🏆" title={t("title")} subtitle={t("subtitle")} />
|
<ContentCard icon="🏆" title={t("title")} subtitle={t("subtitle")} />
|
||||||
|
|
||||||
<ContentCard padded={users.length === 0}>
|
<ContentCard padded={users.length === 0}>
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ export default async function RareCategoryPage({
|
|||||||
badgeBase && cat.badge ? `${badgeBase}/${cat.badge}.gif` : "";
|
badgeBase && cat.badge ? `${badgeBase}/${cat.badge}.gif` : "";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
<ContentCard
|
<ContentCard
|
||||||
icon={badgeSrc ? undefined : "💎"}
|
icon={badgeSrc ? undefined : "💎"}
|
||||||
title={
|
title={
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ export default async function RareValuesPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
<ContentCard icon="💎" title={t("title")} subtitle={t("subtitle")} />
|
<ContentCard icon="💎" title={t("title")} subtitle={t("subtitle")} />
|
||||||
|
|
||||||
{categories.length === 0 ? (
|
{categories.length === 0 ? (
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export default async function RedeemPage() {
|
|||||||
if (!user) redirect("/login");
|
if (!user) redirect("/login");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
<ContentCard icon="🎟️" title={t("title")} subtitle={t("subtitle")} />
|
<ContentCard icon="🎟️" title={t("title")} subtitle={t("subtitle")} />
|
||||||
|
|
||||||
<div className="card-grid sm-2">
|
<div className="card-grid sm-2">
|
||||||
|
|||||||
@@ -2,14 +2,12 @@ import { count, desc, eq } from "drizzle-orm";
|
|||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { getTranslations } from "next-intl/server";
|
import { getTranslations } from "next-intl/server";
|
||||||
|
import { AuthTopBar } from "@/components/auth/auth-top-bar";
|
||||||
import { RegisterForm } from "@/components/auth/register-form";
|
import { RegisterForm } from "@/components/auth/register-form";
|
||||||
import { Clock } from "@/components/clock";
|
|
||||||
import { LanguageSwitcher } from "@/components/language-switcher";
|
|
||||||
import Link from "@/components/link";
|
import Link from "@/components/link";
|
||||||
import { Reveal } from "@/components/motion-reveal";
|
import { Reveal } from "@/components/motion-reveal";
|
||||||
import { UserAvatarThumbnail } from "@/components/shared/user-avatar-thumbnail";
|
import { UserAvatarThumbnail } from "@/components/shared/user-avatar-thumbnail";
|
||||||
import { SurfaceCard } from "@/components/surface-card";
|
import { SurfaceCard } from "@/components/surface-card";
|
||||||
import { ThemeSwitcher } from "@/components/theme-switcher";
|
|
||||||
import { cached } from "@/lib/cache";
|
import { cached } from "@/lib/cache";
|
||||||
import { db, User } from "@/lib/db";
|
import { db, User } from "@/lib/db";
|
||||||
import { resolveHotelName } from "@/lib/hotel-name";
|
import { resolveHotelName } from "@/lib/hotel-name";
|
||||||
@@ -51,74 +49,7 @@ export default async function RegisterPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx-auto w-full max-w-6xl flex flex-col gap-8 pb-16">
|
<div className="mx-auto w-full max-w-6xl flex flex-col gap-8 pb-16">
|
||||||
{/* ── Top Bar ── */}
|
<AuthTopBar hotelName={hotelName} logo={logo} />
|
||||||
<Reveal>
|
|
||||||
<div
|
|
||||||
className="relative flex items-center justify-between rounded-xl border px-5 py-3"
|
|
||||||
style={{
|
|
||||||
background:
|
|
||||||
"color-mix(in srgb, var(--color-surface) 60%, transparent)",
|
|
||||||
backdropFilter: "blur(14px)",
|
|
||||||
WebkitBackdropFilter: "blur(14px)",
|
|
||||||
borderColor:
|
|
||||||
"color-mix(in srgb, var(--color-text-muted) 8%, transparent)",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div className="flex items-center gap-3">
|
|
||||||
{logo ? (
|
|
||||||
<Image
|
|
||||||
src={logo}
|
|
||||||
alt={hotelName}
|
|
||||||
width={100}
|
|
||||||
height={28}
|
|
||||||
className="shrink-0 object-contain"
|
|
||||||
unoptimized
|
|
||||||
style={{ maxHeight: 28, width: "auto", height: "auto" }}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<Image
|
|
||||||
src="/assets/images/icons/lighthouse.png"
|
|
||||||
alt={hotelName}
|
|
||||||
width={28}
|
|
||||||
height={28}
|
|
||||||
className="shrink-0"
|
|
||||||
unoptimized
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<span
|
|
||||||
className="text-sm font-extrabold uppercase tracking-wide"
|
|
||||||
style={{ color: "var(--color-text-readable)" }}
|
|
||||||
>
|
|
||||||
{hotelName}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="flex items-center gap-1.5 rounded-lg px-2 py-1"
|
|
||||||
style={{
|
|
||||||
background:
|
|
||||||
"color-mix(in srgb, var(--color-text-muted) 4%, transparent)",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<LanguageSwitcher />
|
|
||||||
<div
|
|
||||||
className="w-px h-5"
|
|
||||||
style={{
|
|
||||||
background:
|
|
||||||
"color-mix(in srgb, var(--color-text-muted) 12%, transparent)",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Clock />
|
|
||||||
<div
|
|
||||||
className="w-px h-5"
|
|
||||||
style={{
|
|
||||||
background:
|
|
||||||
"color-mix(in srgb, var(--color-text-muted) 12%, transparent)",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<ThemeSwitcher />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Reveal>
|
|
||||||
|
|
||||||
<Reveal>
|
<Reveal>
|
||||||
<div className="flex flex-col gap-8 lg:flex-row lg:items-start">
|
<div className="flex flex-col gap-8 lg:flex-row lg:items-start">
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ export default async function RoomPage({
|
|||||||
.filter(Boolean);
|
.filter(Boolean);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
<p style={{ margin: 0 }}>
|
<p style={{ margin: 0 }}>
|
||||||
<Link href="/" className="btn btn-outline">
|
<Link href="/" className="btn btn-outline">
|
||||||
← Back to the hotel
|
← Back to the hotel
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export default async function SettingsPage() {
|
|||||||
const avatar = avatarImageUrl(user.look);
|
const avatar = avatarImageUrl(user.look);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-6 pb-14">
|
<div className="mx-auto flex w-full max-w-5xl flex-col gap-6 pb-14">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<Reveal>
|
<Reveal>
|
||||||
<SurfaceCard
|
<SurfaceCard
|
||||||
@@ -100,7 +100,7 @@ export default async function SettingsPage() {
|
|||||||
<SurfaceCard
|
<SurfaceCard
|
||||||
title={t("publicProfile")}
|
title={t("publicProfile")}
|
||||||
icon="/assets/images/icons/navigation/me.png"
|
icon="/assets/images/icons/navigation/me.png"
|
||||||
bodyClassName="p-5 flex items-center gap-5"
|
bodyClassName="p-5 flex flex-col sm:flex-row items-center sm:items-center gap-5"
|
||||||
>
|
>
|
||||||
<div className="shrink-0">
|
<div className="shrink-0">
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ export default async function SessionsPage({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
{signedOutAll === "1" ? (
|
{signedOutAll === "1" ? (
|
||||||
<p
|
<p
|
||||||
role="status"
|
role="status"
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ export default async function ShopPage({
|
|||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
{boughtMessage ? (
|
{boughtMessage ? (
|
||||||
<div role="status" style={feedbackStyle("success")}>
|
<div role="status" style={feedbackStyle("success")}>
|
||||||
{boughtMessage}
|
{boughtMessage}
|
||||||
@@ -230,7 +230,7 @@ export default async function ShopPage({
|
|||||||
borderRadius: "var(--radius-sm)",
|
borderRadius: "var(--radius-sm)",
|
||||||
display: "grid",
|
display: "grid",
|
||||||
placeItems: "center",
|
placeItems: "center",
|
||||||
background: "#f8fafc",
|
background: "var(--color-background)",
|
||||||
border: `2px solid ${a.color || "var(--border-color)"}`,
|
border: `2px solid ${a.color || "var(--border-color)"}`,
|
||||||
flexShrink: 0,
|
flexShrink: 0,
|
||||||
overflow: "hidden",
|
overflow: "hidden",
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ export default async function TopUpPage({
|
|||||||
const rate = creditsPerUnit();
|
const rate = creditsPerUnit();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
<ContentCard icon="💳" title={t("title")} subtitle={t("subtitle")} />
|
<ContentCard icon="💳" title={t("title")} subtitle={t("subtitle")} />
|
||||||
|
|
||||||
{sp.status === "cancel" ? (
|
{sp.status === "cancel" ? (
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ export default async function StaffPage() {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
<ContentCard icon="🛡️" title={t("title")} subtitle={t("subtitle")} />
|
<ContentCard icon="🛡️" title={t("title")} subtitle={t("subtitle")} />
|
||||||
|
|
||||||
{teams.length > 0 ? (
|
{teams.length > 0 ? (
|
||||||
@@ -96,26 +96,30 @@ export default async function StaffPage() {
|
|||||||
{staff.length === 0 ? (
|
{staff.length === 0 ? (
|
||||||
<EmptyState icon="🛡️">{t("emptyState")}</EmptyState>
|
<EmptyState icon="🛡️">{t("emptyState")}</EmptyState>
|
||||||
) : (
|
) : (
|
||||||
<table>
|
<div className="table-scroll">
|
||||||
<thead>
|
<table>
|
||||||
<tr>
|
<thead>
|
||||||
<th>{t("colUsername")}</th>
|
<tr>
|
||||||
<th>{t("colRank")}</th>
|
<th>{t("colUsername")}</th>
|
||||||
<th>{t("colMotto")}</th>
|
<th>{t("colRank")}</th>
|
||||||
</tr>
|
<th>{t("colMotto")}</th>
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{staff.map((u) => (
|
|
||||||
<tr key={u.username}>
|
|
||||||
<td>
|
|
||||||
<Link href={`/u/${u.username}`}>{u.username}</Link>
|
|
||||||
</td>
|
|
||||||
<td>{u.rank}</td>
|
|
||||||
<td className="muted">{u.motto || "—"}</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
</thead>
|
||||||
</tbody>
|
<tbody>
|
||||||
</table>
|
{staff.map((u) => (
|
||||||
|
<tr key={u.username}>
|
||||||
|
<td>
|
||||||
|
<Link href={`/u/${u.username}`}>{u.username}</Link>
|
||||||
|
</td>
|
||||||
|
<td>{u.rank}</td>
|
||||||
|
<td className="muted table-cell-truncate">
|
||||||
|
{u.motto || "—"}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</ContentCard>
|
</ContentCard>
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
@@ -317,7 +317,7 @@ export default async function ProfilePage({
|
|||||||
const authorById = new Map(authors.map((a) => [a.id, a]));
|
const authorById = new Map(authors.map((a) => [a.id, a]));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
<main className="page-grid">
|
||||||
{friend === "sent" ? (
|
{friend === "sent" ? (
|
||||||
<div role="status" style={feedbackStyle("success")}>
|
<div role="status" style={feedbackStyle("success")}>
|
||||||
{t("success.sent")}
|
{t("success.sent")}
|
||||||
|
|||||||
@@ -1400,16 +1400,36 @@ a.content-card {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Rich content-page grid (replaces repeated inline `display:grid;gap:1.5rem`). */
|
||||||
|
.page-grid {
|
||||||
|
display: grid;
|
||||||
|
gap: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
/* make tables scroll on small screens */
|
/* make tables scroll on small screens */
|
||||||
@media (max-width: 640px) {
|
@media (max-width: 640px) {
|
||||||
table {
|
table {
|
||||||
|
display: table;
|
||||||
|
}
|
||||||
|
.table-scroll {
|
||||||
display: block;
|
display: block;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
-webkit-overflow-scrolling: touch;
|
-webkit-overflow-scrolling: touch;
|
||||||
border-radius: var(--radius-sm);
|
border-radius: var(--radius-sm);
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
scrollbar-width: thin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Cell text truncation helper for dense tables so long values (motto, URLs)
|
||||||
|
collapse gracefully instead of blowing out row width on small screens. */
|
||||||
|
.table-cell-truncate {
|
||||||
|
max-width: 14rem;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
/* Safe-area insets for notched phones (header/nav/footer sit at screen edges) */
|
/* Safe-area insets for notched phones (header/nav/footer sit at screen edges) */
|
||||||
@supports (padding: max(0px)) {
|
@supports (padding: max(0px)) {
|
||||||
.site-header,
|
.site-header,
|
||||||
|
|||||||
@@ -0,0 +1,95 @@
|
|||||||
|
import Image from "next/image";
|
||||||
|
import { Clock } from "@/components/clock";
|
||||||
|
import { LanguageSwitcher } from "@/components/language-switcher";
|
||||||
|
import { Reveal } from "@/components/motion-reveal";
|
||||||
|
import { ThemeSwitcher } from "@/components/theme-switcher";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shared frosted-glass top bar for the public auth pages (login, register,
|
||||||
|
* etc.). Shows the hotel logo + name on the left and language / clock / theme
|
||||||
|
* controls on the right. Defaults mirror the homepage top bar so auth pages
|
||||||
|
* share one consistent look.
|
||||||
|
*/
|
||||||
|
export function AuthTopBar({
|
||||||
|
hotelName,
|
||||||
|
logo,
|
||||||
|
showHotelName = true,
|
||||||
|
}: {
|
||||||
|
hotelName: string;
|
||||||
|
logo?: string | null;
|
||||||
|
showHotelName?: boolean;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<Reveal>
|
||||||
|
<div
|
||||||
|
className="relative flex items-center justify-between rounded-xl border px-3 py-2.5 sm:px-5 sm:py-3"
|
||||||
|
style={{
|
||||||
|
background:
|
||||||
|
"color-mix(in srgb, var(--color-surface) 60%, transparent)",
|
||||||
|
backdropFilter: "blur(14px)",
|
||||||
|
WebkitBackdropFilter: "blur(14px)",
|
||||||
|
borderColor:
|
||||||
|
"color-mix(in srgb, var(--color-text-muted) 8%, transparent)",
|
||||||
|
boxShadow:
|
||||||
|
"0 1px 3px rgba(0,0,0,0.04), 0 0 0 0.5px color-mix(in srgb, var(--color-text-muted) 6%, transparent)",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="flex items-center gap-2 sm:gap-3">
|
||||||
|
{logo ? (
|
||||||
|
<Image
|
||||||
|
src={logo}
|
||||||
|
alt={hotelName}
|
||||||
|
width={100}
|
||||||
|
height={28}
|
||||||
|
className="shrink-0 object-contain"
|
||||||
|
unoptimized
|
||||||
|
style={{ maxHeight: 28, width: "auto", height: "auto" }}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<Image
|
||||||
|
src="/assets/images/icons/lighthouse.png"
|
||||||
|
alt={hotelName}
|
||||||
|
width={28}
|
||||||
|
height={28}
|
||||||
|
className="shrink-0"
|
||||||
|
unoptimized
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{showHotelName ? (
|
||||||
|
<span
|
||||||
|
className="hidden sm:inline text-sm font-extrabold uppercase tracking-wide"
|
||||||
|
style={{ color: "var(--color-text-readable)" }}
|
||||||
|
>
|
||||||
|
{hotelName}
|
||||||
|
</span>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="flex items-center gap-1 sm:gap-1.5 rounded-lg px-1.5 py-1 sm:px-2"
|
||||||
|
style={{
|
||||||
|
background:
|
||||||
|
"color-mix(in srgb, var(--color-text-muted) 4%, transparent)",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<LanguageSwitcher />
|
||||||
|
<div
|
||||||
|
className="hidden sm:block w-px h-5"
|
||||||
|
style={{
|
||||||
|
background:
|
||||||
|
"color-mix(in srgb, var(--color-text-muted) 12%, transparent)",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Clock />
|
||||||
|
<div
|
||||||
|
className="w-px h-5"
|
||||||
|
style={{
|
||||||
|
background:
|
||||||
|
"color-mix(in srgb, var(--color-text-muted) 12%, transparent)",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<ThemeSwitcher />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Reveal>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in new issue
Block a user