src/components/dives/dive-info-dialog.tsx
Rama main · réplica de lectura del repositorio original.
"use client";
import {
CURRENT_LABELS,
DIVE_TYPE_LABELS,
type Dive,
ENTRY_TYPE_LABELS,
WATER_TYPE_LABELS,
WAVES_LABELS,
WEATHER_LABELS,
} from "@/lib/api/dives";
import { labelOrFallback } from "@/lib/api/labels";
import { useUnits } from "@/hooks/useUnits";
import {
formatDiveDateTime,
formatDurationHoursMinutes,
} from "@/lib/date-time";
import {
formatAltitude,
formatDepth,
formatTemperature,
formatVisibility,
formatWeight,
type UnitSystem,
} from "@/lib/units";
import {
RecordInfoDialog,
type RecordInfoSection,
} from "@/components/ui/record-info-dialog";
const label = (
labels: Readonly<Partial<Record<string, string>>>,
value?: string | null,
) => (value ? labelOrFallback(labels, value) : null);
// The dive's own fields in the dive form's sections and order: one value per
// field. Training, People and Marine life link other records, as do the links
// inside Location and Gear, and Tanks is a list of cylinders the page's own card
// draws - so none of them is here.
export function diveInfoSections(
dive: Dive,
units: UnitSystem,
): RecordInfoSection[] {
const measure = <T,>(
value: T | null | undefined,
format: (v: T) => string,
) => (value == null ? null : format(value));
return [
{
heading: "Location",
facts: [
{
label: "Entry type",
value: label(ENTRY_TYPE_LABELS, dive.entry_type),
},
{ label: "Boat name", value: dive.boat_name },
],
},
{
heading: "Dive info",
facts: [
{ label: "Dive type", value: label(DIVE_TYPE_LABELS, dive.type) },
{ label: "Start time", value: formatDiveDateTime(dive.start_time) },
{ label: "Dive number", value: dive.dive_number },
{
label: "Dive time",
value: formatDurationHoursMinutes(dive.submerged_time),
},
{
label: "Maximum depth",
value: measure(dive.max_depth, (v) => formatDepth(v, units)),
},
{
label: "Average depth",
value: measure(dive.avg_depth, (v) => formatDepth(v, units)),
},
],
},
{
heading: "Environment",
facts: [
{
label: "Bottom temperature",
value: measure(dive.bottom_temperature, (v) =>
formatTemperature(v, units),
),
},
{
label: "Visibility",
value: measure(dive.visibility, (v) => formatVisibility(v, units)),
},
{
label: "Water type",
value: label(WATER_TYPE_LABELS, dive.water_type),
},
{
label: "Altitude",
value: measure(dive.altitude, (v) => formatAltitude(v, units)),
},
{ label: "Waves", value: label(WAVES_LABELS, dive.waves) },
{ label: "Current", value: label(CURRENT_LABELS, dive.current) },
{ label: "Weather", value: label(WEATHER_LABELS, dive.weather) },
{
label: "Air temperature",
value: measure(dive.air_temperature, (v) =>
formatTemperature(v, units),
),
},
],
},
{
heading: "Gear",
facts: [
{
label: "Weight",
value: measure(dive.weight, (v) => formatWeight(v, units)),
},
],
},
{
heading: "Notes",
facts: [
{ label: "Rating", value: measure(dive.rating, (v) => `${v} / 5`) },
{ label: "Tags", value: dive.tags?.join(", ") },
{ label: "Notes", value: dive.notes, wide: true },
],
},
];
}
export function DiveInfoDialog({ dive }: { dive: Dive }) {
const units = useUnits();
return (
<RecordInfoDialog
title="Dive information"
sections={diveInfoSections(dive, units)}
/>
);
}