Siste finjustering frontend
This commit is contained in:
parent
099eac4500
commit
0e6752e010
2 changed files with 85 additions and 68 deletions
|
|
@ -17,6 +17,7 @@ type Facility = {
|
||||||
id: number;
|
id: number;
|
||||||
slug: string;
|
slug: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
description?: string | null;
|
||||||
city?: string | null;
|
city?: string | null;
|
||||||
county?: string | null;
|
county?: string | null;
|
||||||
banetype?: string | null;
|
banetype?: string | null;
|
||||||
|
|
@ -212,6 +213,13 @@ const buildMapUrl = (lat?: number | null, lng?: number | null) => {
|
||||||
return `https://www.google.com/maps/search/?api=1&query=${lat},${lng}`;
|
return `https://www.google.com/maps/search/?api=1&query=${lat},${lng}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const toPlainText = (value: string | null | undefined) =>
|
||||||
|
String(value || "")
|
||||||
|
.replace(/<[^>]+>/g, " ")
|
||||||
|
.replace(/ /gi, " ")
|
||||||
|
.replace(/\s+/g, " ")
|
||||||
|
.trim();
|
||||||
|
|
||||||
const getAreaLabel = (value: string, countyOptions: Array<{ slug: string; label: string }>) => {
|
const getAreaLabel = (value: string, countyOptions: Array<{ slug: string; label: string }>) => {
|
||||||
if (!value) return "Hele Norge";
|
if (!value) return "Hele Norge";
|
||||||
const builtIn = HIERARCHICAL_AREA_OPTIONS.find((option) => option.value === value);
|
const builtIn = HIERARCHICAL_AREA_OPTIONS.find((option) => option.value === value);
|
||||||
|
|
@ -256,7 +264,7 @@ const noteClampStyle: CSSProperties = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const actionIconClassName =
|
const actionIconClassName =
|
||||||
"flex h-10 w-10 items-center justify-center rounded-[0.95rem] border border-[#D5DDD1] bg-white text-[#112015] transition hover:border-[#FF5722] hover:text-[#FF5722]";
|
"flex h-7 w-7 items-center justify-center rounded-[0.8rem] border border-[#D5DDD1] bg-white text-[#112015] transition hover:border-[#FF5722] hover:text-[#FF5722]";
|
||||||
|
|
||||||
export default function FacilitySearch({
|
export default function FacilitySearch({
|
||||||
initialFacilities,
|
initialFacilities,
|
||||||
|
|
@ -580,7 +588,8 @@ export default function FacilitySearch({
|
||||||
/>
|
/>
|
||||||
<div className="absolute inset-0 bg-gradient-to-t from-[#25312A]/65 via-[#25312A]/10 to-transparent" />
|
<div className="absolute inset-0 bg-gradient-to-t from-[#25312A]/65 via-[#25312A]/10 to-transparent" />
|
||||||
|
|
||||||
<div className="absolute left-4 top-4 flex max-w-[calc(100%-2rem)] flex-wrap gap-2">
|
<div className="absolute left-4 top-4 flex max-w-[calc(100%-7rem)] flex-col items-start gap-2">
|
||||||
|
<div className="flex flex-wrap gap-2">
|
||||||
<span
|
<span
|
||||||
className={`rounded-full px-3 py-1.5 text-[10px] font-extrabold uppercase tracking-[0.15em] ${
|
className={`rounded-full px-3 py-1.5 text-[10px] font-extrabold uppercase tracking-[0.15em] ${
|
||||||
STATUS_CLASSES[facility.primaryStatus] || STATUS_CLASSES.ukjent
|
STATUS_CLASSES[facility.primaryStatus] || STATUS_CLASSES.ukjent
|
||||||
|
|
@ -599,6 +608,15 @@ export default function FacilitySearch({
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{facility.status_updated_at && (
|
||||||
|
<div className="absolute right-4 top-4">
|
||||||
|
<span className="inline-flex rounded-full border border-white/15 bg-[#25312A]/72 px-3 py-1.5 text-[10px] font-extrabold uppercase tracking-[0.18em] text-white/90 backdrop-blur-sm shadow-sm">
|
||||||
|
{formatUpdatedDate(facility.status_updated_at)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="absolute bottom-4 left-4 right-4">
|
<div className="absolute bottom-4 left-4 right-4">
|
||||||
<p className="text-[10px] font-extrabold uppercase tracking-[0.22em] text-white/75">
|
<p className="text-[10px] font-extrabold uppercase tracking-[0.22em] text-white/75">
|
||||||
|
|
@ -611,7 +629,8 @@ export default function FacilitySearch({
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
<div className="space-y-5 p-5">
|
<div className="space-y-5 p-5">
|
||||||
<div className="flex flex-wrap gap-2">
|
<div className="flex items-start gap-3">
|
||||||
|
<div className="flex min-w-0 flex-wrap gap-2">
|
||||||
<span className="rounded-full bg-[#EEF5E4] px-3 py-1.5 text-[10px] font-extrabold uppercase tracking-[0.15em] text-[#112015]">
|
<span className="rounded-full bg-[#EEF5E4] px-3 py-1.5 text-[10px] font-extrabold uppercase tracking-[0.15em] text-[#112015]">
|
||||||
{facility.holeValue || "--"} hull
|
{facility.holeValue || "--"} hull
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -619,18 +638,11 @@ export default function FacilitySearch({
|
||||||
{facility.banetype || "Banetype ukjent"}
|
{facility.banetype || "Banetype ukjent"}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
{Number.isFinite(facility.distance) && (
|
||||||
<div className="flex flex-wrap gap-2">
|
<span className="ml-auto shrink-0 self-center rounded-full bg-[#F7F8F3] px-3 py-1.5 text-right text-[10px] font-extrabold uppercase tracking-[0.15em] text-[#617063]">
|
||||||
<span className="rounded-full bg-[#F7F8F3] px-3 py-1.5 text-[10px] font-extrabold uppercase tracking-[0.15em] text-[#617063]">
|
{Math.round(facility.distance)} km unna
|
||||||
Oppdatert {formatUpdatedDate(facility.status_updated_at)}
|
|
||||||
</span>
|
|
||||||
<span className="rounded-full bg-[#F7F8F3] px-3 py-1.5 text-[10px] font-extrabold uppercase tracking-[0.15em] text-[#617063]">
|
|
||||||
{sortMethod === "dist" && Number.isFinite(facility.distance)
|
|
||||||
? `${Math.round(facility.distance)} km unna`
|
|
||||||
: sortMethod === "updated"
|
|
||||||
? "Nyeste status"
|
|
||||||
: "Alfabetisk"}
|
|
||||||
</span>
|
</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{facility.footnote && (
|
{facility.footnote && (
|
||||||
|
|
@ -644,7 +656,15 @@ export default function FacilitySearch({
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="flex flex-wrap justify-center gap-2">
|
{toPlainText(facility.description) && (
|
||||||
|
<p className="text-[15px] leading-7 text-[#617063]">
|
||||||
|
{toPlainText(facility.description)}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="grid grid-cols-[minmax(0,1fr)_auto_minmax(0,1fr)] items-center gap-3 text-sm font-bold text-[#112015]">
|
||||||
|
<span className="truncate text-[#617063]">{facility.phone ? facility.phone : facility.city || "Se detaljer"}</span>
|
||||||
|
<div className="flex items-center justify-self-center gap-1">
|
||||||
{facility.website_url && (
|
{facility.website_url && (
|
||||||
<a href={facility.website_url} target="_blank" rel="noreferrer" className={actionIconClassName} aria-label={`Besøk nettsiden til ${facility.name}`}>
|
<a href={facility.website_url} target="_blank" rel="noreferrer" className={actionIconClassName} aria-label={`Besøk nettsiden til ${facility.name}`}>
|
||||||
<ActionIcon type="web" />
|
<ActionIcon type="web" />
|
||||||
|
|
@ -671,11 +691,8 @@ export default function FacilitySearch({
|
||||||
</a>
|
</a>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
<Link href={`/golfbaner/${facility.slug}`} className="justify-self-end shrink-0 text-right text-[#FF5722] transition hover:text-[#C94F2D]">
|
||||||
<div className="flex items-center justify-between gap-3 text-sm font-bold text-[#112015]">
|
Se anlegg
|
||||||
<span className="truncate text-[#617063]">{facility.phone ? facility.phone : facility.city || "Se detaljer"}</span>
|
|
||||||
<Link href={`/golfbaner/${facility.slug}`} className="shrink-0 text-[#FF5722] transition hover:text-[#C94F2D]">
|
|
||||||
Se anlegg →
|
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -690,7 +707,7 @@ export default function FacilitySearch({
|
||||||
function ActionIcon({ type }: { type: "web" | "booking" | "trophy" | "pin" | "weather" }) {
|
function ActionIcon({ type }: { type: "web" | "booking" | "trophy" | "pin" | "weather" }) {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
className="h-5 w-5"
|
className="h-3.5 w-3.5"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
fill="none"
|
fill="none"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
|
|
|
||||||
|
|
@ -129,12 +129,12 @@ export default function CourseDisplay({ course }: { course: any }) {
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="bg-white rounded-[3rem] shadow-sm border border-gray-200 overflow-hidden mb-12">
|
<div className="mb-12 w-full min-w-0 max-w-[100vw] overflow-x-clip rounded-[2rem] border border-gray-200 bg-white shadow-sm md:rounded-[3rem]">
|
||||||
|
|
||||||
{/* HEADER / KALKULATOR */}
|
{/* HEADER / KALKULATOR */}
|
||||||
<div className="p-8 md:p-12 flex flex-col md:flex-row justify-between items-center gap-8 border-b border-gray-100 bg-white">
|
<div className="flex min-w-0 flex-col items-stretch justify-between gap-5 border-b border-gray-100 bg-white p-4 sm:p-5 md:flex-row md:items-center md:gap-8 md:p-12">
|
||||||
<div className="text-center md:text-left">
|
<div className="min-w-0 text-left">
|
||||||
<h2 className="text-5xl font-black text-[#11280f] tracking-tighter">{course.name}</h2>
|
<h2 className="break-words text-4xl font-black tracking-tighter text-[#11280f] sm:text-5xl">{course.name}</h2>
|
||||||
<p className="text-[#7ca982] font-black uppercase text-xs tracking-[0.2em] mt-2 mb-1">
|
<p className="text-[#7ca982] font-black uppercase text-xs tracking-[0.2em] mt-2 mb-1">
|
||||||
Par {course.par} • {course.length_meters || '--'} meter
|
Par {course.par} • {course.length_meters || '--'} meter
|
||||||
</p>
|
</p>
|
||||||
|
|
@ -143,22 +143,22 @@ export default function CourseDisplay({ course }: { course: any }) {
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid w-full max-w-[28rem] grid-cols-2 gap-4 bg-gray-50 p-4 rounded-[2rem] border border-gray-100 md:flex md:w-auto md:max-w-none md:items-center md:gap-6 md:p-6">
|
<div className="grid w-full min-w-0 max-w-full grid-cols-1 gap-3 rounded-[1.6rem] border border-gray-100 bg-gray-50 p-4 sm:grid-cols-2 md:flex md:w-auto md:max-w-none md:items-center md:gap-6 md:rounded-[2rem] md:p-6">
|
||||||
<div className="flex flex-col"><span className="text-[9px] font-black text-[#7ca982] uppercase ml-1">Kjønn</span>
|
<div className="flex min-w-0 flex-col"><span className="ml-1 text-[9px] font-black uppercase text-[#7ca982]">Kjønn</span>
|
||||||
<select value={gender} onChange={e => { setGender(e.target.value as any); setSelectedTeeIndex(0); }} className="min-w-0 bg-transparent text-[#11280f] font-black outline-none border-b-2 border-[#7ca982]/30 pb-1 cursor-pointer">
|
<select value={gender} onChange={e => { setGender(e.target.value as any); setSelectedTeeIndex(0); }} className="w-full min-w-0 truncate border-b-2 border-[#7ca982]/30 bg-transparent pb-1 pr-6 text-[#11280f] font-black outline-none cursor-pointer">
|
||||||
<option value="herrer">HERRER</option><option value="damer">DAMER</option>
|
<option value="herrer">HERRER</option><option value="damer">DAMER</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col"><span className="text-[9px] font-black text-[#7ca982] uppercase ml-1">Utslag</span>
|
<div className="flex min-w-0 flex-col"><span className="ml-1 text-[9px] font-black uppercase text-[#7ca982]">Utslag</span>
|
||||||
<select value={selectedTeeIndex} onChange={e => setSelectedTeeIndex(Number(e.target.value))} className="min-w-0 bg-transparent text-[#11280f] font-black outline-none border-b-2 border-[#7ca982]/30 pb-1 cursor-pointer">
|
<select value={selectedTeeIndex} onChange={e => setSelectedTeeIndex(Number(e.target.value))} className="w-full min-w-0 truncate border-b-2 border-[#7ca982]/30 bg-transparent pb-1 pr-6 text-[#11280f] font-black outline-none cursor-pointer">
|
||||||
{availableTees.map((t: any, i: number) => (<option key={i} value={i}>{t.navn_utslag || t.navn_utslag_damer}</option>))}
|
{availableTees.map((t: any, i: number) => (<option key={i} value={i}>{t.navn_utslag || t.navn_utslag_damer}</option>))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col"><span className="text-[9px] font-black text-[#7ca982] uppercase ml-1">Ditt HCP</span>
|
<div className="flex min-w-0 flex-col"><span className="ml-1 text-[9px] font-black uppercase text-[#7ca982]">Ditt HCP</span>
|
||||||
<input type="text" value={hcp} onChange={e => setHcp(e.target.value)} className="w-12 bg-transparent text-[#11280f] font-black text-center border-b-2 border-[#7ca982]/30" />
|
<input type="text" value={hcp} onChange={e => setHcp(e.target.value)} className="w-full min-w-0 border-b-2 border-[#7ca982]/30 bg-transparent px-1 text-left font-black text-[#11280f] outline-none md:w-16 md:text-center" />
|
||||||
</div>
|
</div>
|
||||||
<div className="col-span-2 flex items-center justify-center gap-3 rounded-[1.4rem] bg-white px-4 py-3 text-center md:col-span-1 md:pl-6 md:border-l md:border-gray-200 md:bg-transparent md:px-0 md:py-0">
|
<div className="flex items-center justify-between gap-3 rounded-[1.4rem] bg-white px-4 py-3 md:col-span-1 md:justify-center md:border-l md:border-gray-200 md:bg-transparent md:px-0 md:py-0 md:pl-6">
|
||||||
<p className="text-[9px] uppercase font-black text-[#7ca982] mb-1">SpH</p>
|
<p className="mb-1 text-[9px] font-black uppercase text-[#7ca982]">SpH</p>
|
||||||
<p className="text-4xl font-black text-[#11280f] leading-none">{playingHandicap || 0}</p>
|
<p className="text-4xl font-black text-[#11280f] leading-none">{playingHandicap || 0}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue