hellth-hub/apps/admin/app/(authed)/wearables/page.tsx

110 lines
5 KiB
TypeScript
Raw Permalink Normal View History

"use client";
import {
ArrowPathIcon,
BoltIcon,
CheckCircleIcon,
DevicePhoneMobileIcon,
ExclamationTriangleIcon,
} from "@heroicons/react/24/outline";
import { trpc } from "@/lib/trpc";
const plannedImports = [
"Schritte und aktive Minuten",
"Trainingseinheiten von der Pixel Watch",
"Aktivitätskalorien als optionaler Sportbonus",
"Dublettenprüfung über externe Aktivitäts-IDs",
"Punktevergabe für importierte Aktivitäten",
];
export default function WearablesPage() {
const connectionsQuery = trpc.health.wearableConnections.useQuery();
const connections = connectionsQuery.data ?? [];
const fitbit = connections.find((connection) => connection.provider === "fitbit");
return (
<div className="mx-auto max-w-5xl space-y-5 pb-24">
<header className="overflow-hidden rounded-[2rem] bg-gray-950 p-6 text-white shadow-sm">
<div className="flex flex-col gap-6 sm:flex-row sm:items-end sm:justify-between">
<div>
<p className="text-sm font-black uppercase text-emerald-300">Pixel Watch & Fitbit</p>
<h1 className="mt-2 text-4xl font-black tracking-normal">Wearables</h1>
<p className="mt-3 max-w-2xl text-sm font-semibold text-white/60">
Importiere Aktivitäten aus deiner Uhr und verwandle sie in Sportbonus, Aktivitätspunkte und bessere Wochenprognosen.
</p>
</div>
<div className="grid h-28 w-28 place-items-center rounded-full bg-white text-gray-950 ring-[12px] ring-white/10">
<DevicePhoneMobileIcon className="h-14 w-14" />
</div>
</div>
</header>
<section className="grid gap-4 lg:grid-cols-[1fr_0.8fr]">
<div className="rounded-[2rem] bg-white p-5 shadow-sm ring-1 ring-gray-100">
<div className="flex items-start justify-between gap-4">
<div>
<h2 className="text-2xl font-black text-gray-950">Fitbit</h2>
<p className="mt-2 text-sm font-semibold text-gray-400">
Empfohlener erster Weg für die Pixel Watch. Google Fit wird nicht mehr als neue Basis aufgebaut; Health Connect bleibt als spätere Android-Brücke vorgesehen.
</p>
</div>
<span className={`rounded-full px-3 py-1 text-xs font-black ${fitbit ? "bg-emerald-50 text-emerald-700" : "bg-amber-50 text-amber-700"}`}>
{fitbit ? "verbunden" : "vorbereitet"}
</span>
</div>
<div className="mt-5 rounded-3xl bg-gray-50 p-4">
{fitbit ? (
<div className="flex items-center gap-3">
<CheckCircleIcon className="h-7 w-7 text-emerald-600" />
<div>
<p className="text-sm font-black text-gray-950">Fitbit-Verbindung aktiv</p>
<p className="text-xs font-bold text-gray-400">
Letzter Sync: {fitbit.lastSyncAt ? new Date(fitbit.lastSyncAt).toLocaleString("de-DE") : "noch nicht synchronisiert"}
</p>
</div>
</div>
) : (
<div className="flex items-start gap-3">
<ExclamationTriangleIcon className="h-7 w-7 text-amber-600" />
<div>
<p className="text-sm font-black text-gray-950">OAuth-Verbindung ist der nächste technische Schritt</p>
<p className="mt-1 text-xs font-bold text-gray-400">
Die Tabellen und API-Struktur sind vorbereitet. Für den echten Login fehlen noch Fitbit Client-ID, Secret und Callback-Route.
</p>
</div>
</div>
)}
</div>
<div className="mt-5 grid gap-3 sm:grid-cols-2">
<button type="button" disabled className="inline-flex items-center justify-center gap-2 rounded-full bg-gray-950 px-4 py-4 text-sm font-black text-white disabled:opacity-40">
<DevicePhoneMobileIcon className="h-5 w-5" />
Fitbit verbinden
</button>
<button type="button" disabled className="inline-flex items-center justify-center gap-2 rounded-full bg-gray-100 px-4 py-4 text-sm font-black text-gray-950 disabled:opacity-50">
<ArrowPathIcon className="h-5 w-5" />
Jetzt synchronisieren
</button>
</div>
</div>
<aside className="rounded-[2rem] bg-white p-5 shadow-sm ring-1 ring-gray-100">
<div className="flex items-center gap-3">
<BoltIcon className="h-8 w-8 text-emerald-500" />
<h2 className="text-xl font-black text-gray-950">Geplanter Import</h2>
</div>
<div className="mt-5 space-y-3">
{plannedImports.map((item) => (
<div key={item} className="flex items-center gap-3 rounded-2xl bg-gray-50 p-3">
<CheckCircleIcon className="h-5 w-5 text-emerald-600" />
<span className="text-sm font-bold text-gray-600">{item}</span>
</div>
))}
</div>
</aside>
</section>
</div>
);
}