fix(auth): resolve redirect loop and mount Better-Auth as sub-app (#144)
## Changes - Replace toNodeHandler with auth.handler(c.req.raw) sub-app mount for Hono compatibility - Add /api/auth/ path skip in authMiddleware and resolveStaffMiddleware - Add OIDC_INTERNAL_BASE env var for split-horizon (hairpin NAT) URL resolution - Replace render-time signIn.social() with LoginPage component (fixes redirect loop) - Change auth-client baseURL to relative (empty string) for deployed environments - Add POST /api/portal/appointments/:id/reschedule endpoint with session auth - Add RescheduleFlow modal, PetForm component, and wire Dashboard/Appointments UI ## CTO Note Auth fix is P0-critical. Portal mock data (UAT blocker) predates this PR and is tracked separately in GRO-218. Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit was merged in pull request #144.
This commit is contained in:
committed by
GitHub
parent
3a31ad71c2
commit
6872342d8f
@@ -1,6 +1,7 @@
|
||||
import { useState } from "react";
|
||||
import { User, Lock, PawPrint, FileCheck, Plus, Archive } from "lucide-react";
|
||||
import { CUSTOMER, PETS, SIGNED_AGREEMENTS } from "../mockData.js";
|
||||
import { PetForm } from "./PetForm.js";
|
||||
|
||||
interface Props {
|
||||
readOnly: boolean;
|
||||
@@ -112,6 +113,20 @@ function PasswordChange({ readOnly }: { readOnly: boolean }) {
|
||||
}
|
||||
|
||||
function ManagePets({ readOnly }: { readOnly: boolean }) {
|
||||
const [editingPetId, setEditingPetId] = useState<string | null>(null);
|
||||
const [showAddForm, setShowAddForm] = useState(false);
|
||||
const editingPet = editingPetId ? PETS.find(p => p.id === editingPetId) ?? undefined : undefined;
|
||||
|
||||
if (editingPet || showAddForm) {
|
||||
return (
|
||||
<PetForm
|
||||
pet={editingPet ?? undefined}
|
||||
onSave={() => { setEditingPetId(null); setShowAddForm(false); }}
|
||||
onCancel={() => { setEditingPetId(null); setShowAddForm(false); }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
{PETS.map(pet => (
|
||||
@@ -126,17 +141,12 @@ function ManagePets({ readOnly }: { readOnly: boolean }) {
|
||||
{!readOnly && (
|
||||
<div className="flex gap-2">
|
||||
<button
|
||||
disabled
|
||||
title="Pet editing coming soon"
|
||||
className="px-3 py-1.5 border border-stone-200 rounded-lg text-xs text-stone-400 cursor-not-allowed"
|
||||
onClick={() => setEditingPetId(pet.id)}
|
||||
className="px-3 py-1.5 border border-stone-200 rounded-lg text-xs text-stone-600 hover:bg-stone-50"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
<button
|
||||
disabled
|
||||
title="Pet archiving coming soon"
|
||||
className="p-1.5 border border-stone-200 rounded-lg text-stone-300 cursor-not-allowed"
|
||||
>
|
||||
<button className="p-1.5 border border-stone-200 rounded-lg text-stone-400 hover:text-amber-600 hover:border-amber-200">
|
||||
<Archive size={14} />
|
||||
</button>
|
||||
</div>
|
||||
@@ -145,9 +155,8 @@ function ManagePets({ readOnly }: { readOnly: boolean }) {
|
||||
))}
|
||||
{!readOnly && (
|
||||
<button
|
||||
disabled
|
||||
title="Adding pets coming soon"
|
||||
className="w-full flex items-center justify-center gap-2 py-3 border-2 border-dashed border-stone-300 rounded-2xl text-sm text-stone-400 cursor-not-allowed"
|
||||
onClick={() => setShowAddForm(true)}
|
||||
className="w-full flex items-center justify-center gap-2 py-3 border-2 border-dashed border-stone-300 rounded-2xl text-sm text-stone-500 hover:border-(--color-accent) hover:text-(--color-accent-dark) transition-colors"
|
||||
>
|
||||
<Plus size={16} />
|
||||
Add New Pet
|
||||
|
||||
Reference in New Issue
Block a user