create public layout and admin and fix escrow and refund

This commit is contained in:
arifal
2026-05-12 00:05:30 +07:00
parent a07942c4b4
commit 958514d575
48 changed files with 1928 additions and 18 deletions
+227
View File
@@ -0,0 +1,227 @@
import { ImageResponse } from "next/og";
import { tripService } from "@/server/services/trip.service";
import { formatRupiah } from "@/lib/utils";
import { formatTripCalendarDateRangeLong } from "@/lib/trip-dates";
import { siteConfig } from "@/lib/site";
export const alt = `${siteConfig.name} — Open Trip & Aktivitas Bareng`;
export const size = { width: 1200, height: 630 };
export const contentType = "image/png";
export default async function TripOgImage({
params,
}: {
params: Promise<{ id: string }>;
}) {
const { id } = await params;
let trip;
try {
trip = await tripService.getTripById(id);
} catch {
return new ImageResponse(
(
<div
style={{
width: "100%",
height: "100%",
display: "flex",
alignItems: "center",
justifyContent: "center",
background:
"linear-gradient(135deg, #14532d 0%, #16a34a 60%, #0c4a6e 100%)",
color: "white",
fontSize: 96,
fontWeight: 800,
letterSpacing: -2,
}}
>
{siteConfig.name}
</div>
),
{ ...size }
);
}
const cover = trip.images[0]?.url;
const dateLabel = formatTripCalendarDateRangeLong(trip.date, trip.endDate);
const price = formatRupiah(trip.price);
return new ImageResponse(
(
<div
style={{
width: "100%",
height: "100%",
display: "flex",
position: "relative",
background: "#0a0a0a",
color: "white",
fontFamily: "sans-serif",
}}
>
{cover && (
// eslint-disable-next-line @next/next/no-img-element
<img
src={cover}
alt=""
width={1200}
height={630}
style={{
position: "absolute",
top: 0,
left: 0,
width: "100%",
height: "100%",
objectFit: "cover",
filter: "brightness(0.45) saturate(1.05)",
}}
/>
)}
<div
style={{
position: "absolute",
inset: 0,
background:
"linear-gradient(135deg, rgba(20,83,45,0.88) 0%, rgba(10,10,10,0.5) 55%, rgba(12,74,110,0.85) 100%)",
display: "flex",
}}
/>
<div
style={{
position: "relative",
display: "flex",
flexDirection: "column",
justifyContent: "space-between",
padding: 64,
width: "100%",
height: "100%",
}}
>
{/* Top: brand badge */}
<div style={{ display: "flex", alignItems: "center", gap: 14 }}>
<div
style={{
display: "flex",
alignItems: "center",
gap: 10,
background: "rgba(22,163,74,0.25)",
border: "1px solid rgba(74,222,128,0.45)",
borderRadius: 999,
padding: "10px 22px",
fontSize: 24,
fontWeight: 600,
color: "#86efac",
}}
>
<span style={{ fontSize: 28 }}>🤝</span>
<span>Open Trip Bareng</span>
</div>
</div>
{/* Middle: title + destination */}
<div style={{ display: "flex", flexDirection: "column", gap: 16 }}>
<div
style={{
fontSize: trip.title.length > 40 ? 64 : 76,
fontWeight: 800,
letterSpacing: -2,
lineHeight: 1.05,
display: "flex",
maxWidth: 1050,
}}
>
{trip.title}
</div>
<div
style={{
fontSize: 32,
color: "#bbf7d0",
display: "flex",
alignItems: "center",
gap: 10,
}}
>
<span>📍</span>
<span>
{trip.destination} · {trip.location}
</span>
</div>
</div>
{/* Bottom: date / price / brand */}
<div
style={{
display: "flex",
alignItems: "flex-end",
justifyContent: "space-between",
gap: 32,
}}
>
<div style={{ display: "flex", flexDirection: "column", gap: 22 }}>
<div
style={{
display: "flex",
alignItems: "center",
gap: 16,
fontSize: 26,
color: "#e0f2fe",
}}
>
<span style={{ fontSize: 30 }}>📅</span>
<span>{dateLabel}</span>
</div>
<div
style={{
display: "flex",
alignItems: "baseline",
gap: 14,
}}
>
<span style={{ fontSize: 22, color: "#86efac" }}>Mulai</span>
<span
style={{
fontSize: 56,
fontWeight: 800,
color: "#4ade80",
letterSpacing: -1,
}}
>
{price}
</span>
<span style={{ fontSize: 22, color: "#86efac" }}>/ orang</span>
</div>
</div>
<div
style={{
display: "flex",
flexDirection: "column",
alignItems: "flex-end",
gap: 6,
}}
>
<div
style={{
fontSize: 48,
fontWeight: 800,
letterSpacing: -2,
display: "flex",
}}
>
<span>Se</span>
<span style={{ color: "#4ade80" }}>Trip</span>
</div>
<div style={{ fontSize: 18, color: "#a3a3a3" }}>
{siteConfig.slogan}
</div>
</div>
</div>
</div>
</div>
),
{ ...size }
);
}