feat: add Toaster, notification bell, search, unread badges, last login, recent rooms, hotel alerts, quick room entry, friend requests in top bar
This commit is contained in:
1 parent
a906d671fb
commit
3284e5a915
5 files changed
+484
-19
No files matched your search
@@ -69,7 +69,7 @@ export default async function MePage({
|
||||
|
||||
let content: ReactNode;
|
||||
try {
|
||||
const [user, imagerBase, hotelName, neededRaw, amountRaw, currencyRaw] =
|
||||
const [user, imagerBase, hotelName, neededRaw, amountRaw, currencyRaw, alertRaw, recentRooms] =
|
||||
await Promise.all([
|
||||
prisma.user.findUnique({
|
||||
where: { id: userId },
|
||||
@@ -81,6 +81,8 @@ export default async function MePage({
|
||||
rank: true,
|
||||
credits: true,
|
||||
accountCreated: true,
|
||||
lastLogin: true,
|
||||
lastOnline: true,
|
||||
},
|
||||
}),
|
||||
siteSettings.get(
|
||||
@@ -113,6 +115,14 @@ export default async function MePage({
|
||||
select: { value: true },
|
||||
})
|
||||
.catch(() => null),
|
||||
siteSettings.get("hotel_alert_banner", ""),
|
||||
prisma.rooms
|
||||
.findMany({
|
||||
orderBy: { id: "desc" },
|
||||
select: { id: true, name: true, ownerName: true, users: true, usersMax: true },
|
||||
take: 6,
|
||||
})
|
||||
.catch(() => []),
|
||||
]);
|
||||
|
||||
if (!user) throw new Error("user-not-found");
|
||||
@@ -169,6 +179,12 @@ export default async function MePage({
|
||||
const registered = new Date(user.accountCreated * 1000)
|
||||
.toISOString()
|
||||
.slice(0, 10);
|
||||
const lastLoginDate = user.lastLogin
|
||||
? new Date(user.lastLogin * 1000).toISOString().slice(0, 10)
|
||||
: "Never";
|
||||
const lastOnlineDate = user.lastOnline
|
||||
? new Date(user.lastOnline * 1000).toISOString().slice(0, 10)
|
||||
: "Never";
|
||||
const referralLink = `/register?ref=${encodeURIComponent(user.username)}`;
|
||||
|
||||
const imager = imagerBase ?? "https://www.habbo.com/habbo-imaging/avatarimage";
|
||||
@@ -256,6 +272,23 @@ export default async function MePage({
|
||||
</div>
|
||||
</Reveal>
|
||||
|
||||
{/* ── Hotel alert banner ── */}
|
||||
{alertRaw ? (
|
||||
<Reveal delay={0.05}>
|
||||
<div
|
||||
className="rounded-2xl border px-6 py-4 text-center"
|
||||
style={{
|
||||
background: "color-mix(in srgb, var(--color-accent) 12%, transparent)",
|
||||
borderColor: "color-mix(in srgb, var(--color-accent) 25%, transparent)",
|
||||
}}
|
||||
>
|
||||
<p className="text-sm font-bold" style={{ color: "var(--color-accent)" }}>
|
||||
{alertRaw}
|
||||
</p>
|
||||
</div>
|
||||
</Reveal>
|
||||
) : null}
|
||||
|
||||
{/* ── Enter hotel ── */}
|
||||
<Reveal delay={0.05}>
|
||||
<Link
|
||||
@@ -285,7 +318,7 @@ export default async function MePage({
|
||||
{[
|
||||
{ value: user.credits.toLocaleString(), label: "Credits" },
|
||||
{ value: `Rank ${user.rank}`, label: "Hotel rank" },
|
||||
{ value: registered, label: "Registered" },
|
||||
{ value: lastLoginDate, label: "Last login" },
|
||||
].map((s) => (
|
||||
<div
|
||||
key={s.label}
|
||||
@@ -489,6 +522,62 @@ export default async function MePage({
|
||||
</div>
|
||||
</div>
|
||||
</Reveal>
|
||||
{/* ── Recent rooms ── */}
|
||||
{recentRooms.length > 0 && (
|
||||
<Reveal delay={0.25}>
|
||||
<div
|
||||
className="rounded-2xl border p-5"
|
||||
style={{
|
||||
background: "var(--color-surface)",
|
||||
borderColor: "color-mix(in srgb, var(--color-text-muted) 10%, transparent)",
|
||||
}}
|
||||
>
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<div>
|
||||
<h2
|
||||
className="text-lg font-black tracking-tight"
|
||||
style={{ color: "var(--color-text-readable)" }}
|
||||
>
|
||||
Recent rooms
|
||||
</h2>
|
||||
<p className="text-xs mt-0.5" style={{ color: "var(--color-text-muted)" }}>
|
||||
Newest rooms in the hotel
|
||||
</p>
|
||||
</div>
|
||||
<Link
|
||||
href="/community"
|
||||
className="text-xs font-bold hover:underline shrink-0"
|
||||
style={{ color: "var(--color-primary)" }}
|
||||
>
|
||||
View all
|
||||
</Link>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 sm:grid-cols-3 gap-3">
|
||||
{recentRooms.map((room) => (
|
||||
<Link
|
||||
key={room.id}
|
||||
href={`/room/${room.id}`}
|
||||
className="block rounded-xl border p-3 transition-all duration-200 hover:-translate-y-0.5"
|
||||
style={{
|
||||
background: "color-mix(in srgb, var(--color-primary) 4%, transparent)",
|
||||
borderColor: "color-mix(in srgb, var(--color-text-muted) 10%, transparent)",
|
||||
}}
|
||||
>
|
||||
<p
|
||||
className="text-sm font-extrabold truncate"
|
||||
style={{ color: "var(--color-text-readable)" }}
|
||||
>
|
||||
{room.name}
|
||||
</p>
|
||||
<p className="text-[10px] font-semibold mt-0.5" style={{ color: "var(--color-text-muted)" }}>
|
||||
{room.ownerName} · {room.users}/{room.usersMax}
|
||||
</p>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</Reveal>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
} catch {
|
||||
|
||||
Reference in new issue
Block a user