feat(health): emergency vet with OSM search and map
- EmergencyVet model: name, address, phone, website, lat, lng (1:1 to Pet) - health router: getEmergencyVet, setEmergencyVet, deleteEmergencyVet - EmergencyVetSection: Nominatim search (debounced 500ms, OSM attribution), result dropdown auto-fills address + coordinates, manual override for all fields - OSM iframe map (no API key) with "In Karte öffnen" link; shown in edit mode as coordinate preview and in view mode after save - Health card (public): red-accented emergency vet block with phone link, website link and OSM map; map hidden on print (print:hidden) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
c9f385a9fa
commit
d17d71e55a
5 files changed
+505
-4
No files matched your search
@@ -132,6 +132,43 @@ export const healthRouter = router({
|
||||
return { success: true };
|
||||
}),
|
||||
|
||||
// ── Emergency Vet ────────────────────────────────────────────────────────────
|
||||
|
||||
getEmergencyVet: protectedProcedure
|
||||
.input(z.object({ petId: z.string().min(1) }))
|
||||
.query(async ({ ctx, input }) => {
|
||||
await assertOwner(ctx.prisma, input.petId, ctx.userId);
|
||||
return ctx.prisma.emergencyVet.findUnique({ where: { petId: input.petId } });
|
||||
}),
|
||||
|
||||
setEmergencyVet: protectedProcedure
|
||||
.input(z.object({
|
||||
petId: z.string().min(1),
|
||||
name: z.string().min(1).max(150),
|
||||
address: z.string().max(300).optional().nullable(),
|
||||
phone: z.string().max(30).optional().nullable(),
|
||||
website: z.string().max(200).optional().nullable(),
|
||||
lat: z.number().optional().nullable(),
|
||||
lng: z.number().optional().nullable(),
|
||||
}))
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
await assertOwner(ctx.prisma, input.petId, ctx.userId);
|
||||
const { petId, ...data } = input;
|
||||
return ctx.prisma.emergencyVet.upsert({
|
||||
where: { petId },
|
||||
update: data,
|
||||
create: { petId, ...data },
|
||||
});
|
||||
}),
|
||||
|
||||
deleteEmergencyVet: protectedProcedure
|
||||
.input(z.object({ petId: z.string().min(1) }))
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
await assertOwner(ctx.prisma, input.petId, ctx.userId);
|
||||
await ctx.prisma.emergencyVet.deleteMany({ where: { petId: input.petId } });
|
||||
return { success: true };
|
||||
}),
|
||||
|
||||
// ── Health Card ──────────────────────────────────────────────────────────────
|
||||
|
||||
getOrCreateCard: protectedProcedure
|
||||
|
||||
Reference in new issue
Block a user