diff --git a/src/features/kontakte/components/contact-card.tsx b/src/features/kontakte/components/contact-card.tsx
new file mode 100644
index 0000000..9861f9a
--- /dev/null
+++ b/src/features/kontakte/components/contact-card.tsx
@@ -0,0 +1,56 @@
+import { Badge } from "@/shared/components/ui/badge";
+import { Card, CardContent } from "@/shared/components/ui/card";
+import type { KontaktErgebnis } from "@/shared/db/schema";
+import { ERGEBNIS_LABELS } from "@/shared/lib/constants";
+
+interface ContactCardProps {
+ id: number;
+ name: string;
+ stadt: string | null;
+ letzterKontakt: string | null;
+ letztesErgebnis: string | null;
+ kontakteGesamt: number;
+}
+
+const ergebnisVariant: Record<
+ KontaktErgebnis,
+ "default" | "secondary" | "destructive" | "outline"
+> = {
+ zusage: "default",
+ warteliste: "secondary",
+ absage: "destructive",
+ keine_antwort: "outline",
+};
+
+export function ContactCard({
+ name,
+ stadt,
+ letzterKontakt,
+ letztesErgebnis,
+ kontakteGesamt,
+}: ContactCardProps) {
+ return (
+
+
+
+
{name}
+ {stadt &&
{stadt}
}
+
+ {kontakteGesamt} Kontakt{kontakteGesamt !== 1 ? "e" : ""}
+ {letzterKontakt && <> · Letzter: {letzterKontakt}>}
+
+
+ {letztesErgebnis && (
+
+ {ERGEBNIS_LABELS[letztesErgebnis as KontaktErgebnis] ??
+ letztesErgebnis}
+
+ )}
+
+
+ );
+}
diff --git a/src/features/kontakte/components/contact-form.tsx b/src/features/kontakte/components/contact-form.tsx
new file mode 100644
index 0000000..b82f610
--- /dev/null
+++ b/src/features/kontakte/components/contact-form.tsx
@@ -0,0 +1,249 @@
+import { useForm } from "@tanstack/react-form";
+import { Link, useNavigate } from "@tanstack/react-router";
+import { createKontakt, createTherapeut } from "@/features/kontakte/hooks";
+import { Button } from "@/shared/components/ui/button";
+import { Separator } from "@/shared/components/ui/separator";
+import type { KontaktErgebnis, KontaktKanal } from "@/shared/db/schema";
+import { kontaktErgebnisEnum, kontaktKanalEnum } from "@/shared/db/schema";
+import { ERGEBNIS_LABELS, KANAL_LABELS } from "@/shared/lib/constants";
+
+function todayISO() {
+ const d = new Date();
+ const y = d.getFullYear();
+ const m = String(d.getMonth() + 1).padStart(2, "0");
+ const day = String(d.getDate()).padStart(2, "0");
+ return `${y}-${m}-${day}`;
+}
+
+export function ContactForm() {
+ const navigate = useNavigate();
+
+ const form = useForm({
+ defaultValues: {
+ name: "",
+ stadt: "",
+ telefon: "",
+ email: "",
+ datum: todayISO(),
+ kanal: "telefon" as KontaktKanal,
+ ergebnis: "keine_antwort" as KontaktErgebnis,
+ notiz: "",
+ },
+ onSubmit: async ({ value }) => {
+ if (!value.name.trim()) return;
+
+ const therapeutId = await createTherapeut({
+ name: value.name.trim(),
+ adresse: "",
+ plz: "",
+ stadt: value.stadt.trim(),
+ telefon: value.telefon.trim(),
+ email: value.email.trim(),
+ website: "",
+ therapieform: "",
+ });
+
+ await createKontakt({
+ therapeut_id: therapeutId,
+ datum: value.datum,
+ kanal: value.kanal,
+ ergebnis: value.ergebnis,
+ notiz: value.notiz.trim() || "",
+ });
+
+ navigate({ to: "/kontakte" });
+ },
+ });
+
+ const inputClasses =
+ "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-xs transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring";
+
+ return (
+
+ );
+}
diff --git a/src/features/kontakte/components/contact-list.tsx b/src/features/kontakte/components/contact-list.tsx
new file mode 100644
index 0000000..3aeff06
--- /dev/null
+++ b/src/features/kontakte/components/contact-list.tsx
@@ -0,0 +1,46 @@
+import { Link } from "@tanstack/react-router";
+import { useTherapeutenListe } from "@/features/kontakte/hooks";
+import { Button } from "@/shared/components/ui/button";
+import { ContactCard } from "./contact-card";
+
+export function ContactList() {
+ const { data, loading } = useTherapeutenListe();
+
+ if (loading) return Laden…
;
+
+ return (
+
+
+
Kontakte
+
+
+
+ {data.length === 0 ? (
+
+
+ Noch keine Therapeut:innen erfasst.
+
+
+
+ ) : (
+
+ {data.map((t) => (
+
+ ))}
+
+ )}
+
+ );
+}
diff --git a/src/routeTree.gen.ts b/src/routeTree.gen.ts
index eff7f13..3333729 100644
--- a/src/routeTree.gen.ts
+++ b/src/routeTree.gen.ts
@@ -10,6 +10,8 @@
import { Route as rootRouteImport } from './routes/__root'
import { Route as IndexRouteImport } from './routes/index'
+import { Route as KontakteIndexRouteImport } from './routes/kontakte/index'
+import { Route as KontakteNeuRouteImport } from './routes/kontakte/neu'
import { Route as OnboardingIndexRouteImport } from './routes/onboarding/index'
import { Route as ProzessIndexRouteImport } from './routes/prozess/index'
@@ -28,33 +30,57 @@ const OnboardingIndexRoute = OnboardingIndexRouteImport.update({
path: '/onboarding/',
getParentRoute: () => rootRouteImport,
} as any)
+const KontakteIndexRoute = KontakteIndexRouteImport.update({
+ id: '/kontakte/',
+ path: '/kontakte/',
+ getParentRoute: () => rootRouteImport,
+} as any)
+const KontakteNeuRoute = KontakteNeuRouteImport.update({
+ id: '/kontakte/neu',
+ path: '/kontakte/neu',
+ getParentRoute: () => rootRouteImport,
+} as any)
export interface FileRoutesByFullPath {
'/': typeof IndexRoute
+ '/kontakte/neu': typeof KontakteNeuRoute
+ '/kontakte/': typeof KontakteIndexRoute
'/onboarding/': typeof OnboardingIndexRoute
'/prozess/': typeof ProzessIndexRoute
}
export interface FileRoutesByTo {
'/': typeof IndexRoute
+ '/kontakte/neu': typeof KontakteNeuRoute
+ '/kontakte': typeof KontakteIndexRoute
'/onboarding': typeof OnboardingIndexRoute
'/prozess': typeof ProzessIndexRoute
}
export interface FileRoutesById {
__root__: typeof rootRouteImport
'/': typeof IndexRoute
+ '/kontakte/neu': typeof KontakteNeuRoute
+ '/kontakte/': typeof KontakteIndexRoute
'/onboarding/': typeof OnboardingIndexRoute
'/prozess/': typeof ProzessIndexRoute
}
export interface FileRouteTypes {
fileRoutesByFullPath: FileRoutesByFullPath
- fullPaths: '/' | '/onboarding/' | '/prozess/'
+ fullPaths: '/' | '/kontakte/neu' | '/kontakte/' | '/onboarding/' | '/prozess/'
fileRoutesByTo: FileRoutesByTo
- to: '/' | '/onboarding' | '/prozess'
- id: '__root__' | '/' | '/onboarding/' | '/prozess/'
+ to: '/' | '/kontakte/neu' | '/kontakte' | '/onboarding' | '/prozess'
+ id:
+ | '__root__'
+ | '/'
+ | '/kontakte/neu'
+ | '/kontakte/'
+ | '/onboarding/'
+ | '/prozess/'
fileRoutesById: FileRoutesById
}
export interface RootRouteChildren {
IndexRoute: typeof IndexRoute
+ KontakteNeuRoute: typeof KontakteNeuRoute
+ KontakteIndexRoute: typeof KontakteIndexRoute
OnboardingIndexRoute: typeof OnboardingIndexRoute
ProzessIndexRoute: typeof ProzessIndexRoute
}
@@ -82,11 +108,27 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof OnboardingIndexRouteImport
parentRoute: typeof rootRouteImport
}
+ '/kontakte/': {
+ id: '/kontakte/'
+ path: '/kontakte'
+ fullPath: '/kontakte/'
+ preLoaderRoute: typeof KontakteIndexRouteImport
+ parentRoute: typeof rootRouteImport
+ }
+ '/kontakte/neu': {
+ id: '/kontakte/neu'
+ path: '/kontakte/neu'
+ fullPath: '/kontakte/neu'
+ preLoaderRoute: typeof KontakteNeuRouteImport
+ parentRoute: typeof rootRouteImport
+ }
}
}
const rootRouteChildren: RootRouteChildren = {
IndexRoute: IndexRoute,
+ KontakteNeuRoute: KontakteNeuRoute,
+ KontakteIndexRoute: KontakteIndexRoute,
OnboardingIndexRoute: OnboardingIndexRoute,
ProzessIndexRoute: ProzessIndexRoute,
}
diff --git a/src/routes/__root.tsx b/src/routes/__root.tsx
index 101409f..10ed980 100644
--- a/src/routes/__root.tsx
+++ b/src/routes/__root.tsx
@@ -1,11 +1,27 @@
-import { Outlet, createRootRoute } from "@tanstack/react-router"
+import { createRootRoute, Link, Outlet } from "@tanstack/react-router";
export const Route = createRootRoute({
component: () => (
-
-
+
+
+
),
-})
+});
diff --git a/src/routes/kontakte/index.tsx b/src/routes/kontakte/index.tsx
new file mode 100644
index 0000000..51f6908
--- /dev/null
+++ b/src/routes/kontakte/index.tsx
@@ -0,0 +1,6 @@
+import { createFileRoute } from "@tanstack/react-router";
+import { ContactList } from "@/features/kontakte/components/contact-list";
+
+export const Route = createFileRoute("/kontakte/")({
+ component: () => ,
+});
diff --git a/src/routes/kontakte/neu.tsx b/src/routes/kontakte/neu.tsx
new file mode 100644
index 0000000..a30ed11
--- /dev/null
+++ b/src/routes/kontakte/neu.tsx
@@ -0,0 +1,6 @@
+import { createFileRoute } from "@tanstack/react-router";
+import { ContactForm } from "@/features/kontakte/components/contact-form";
+
+export const Route = createFileRoute("/kontakte/neu")({
+ component: () => ,
+});