feat: núcleo de tickets com Convex (CRUD, play, comentários com anexos) + auth placeholder; docs em AGENTS.md; toasts e updates otimistas; mapeadores Zod; refinos PT-BR e layout do painel de detalhes
This commit is contained in:
parent
2230590e57
commit
27b103cb46
97 changed files with 15117 additions and 15715 deletions
50
web/src/lib/auth-client.tsx
Normal file
50
web/src/lib/auth-client.tsx
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
"use client";
|
||||
|
||||
import React, { createContext, useContext, useEffect, useMemo, useState } from "react";
|
||||
import { useMutation } from "convex/react";
|
||||
|
||||
// Lazy import to avoid build errors before convex is generated
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
import { api } from "../../convex/_generated/api";
|
||||
|
||||
export type DemoUser = { name: string; email: string; avatarUrl?: string } | null;
|
||||
|
||||
type AuthContextValue = {
|
||||
demoUser: DemoUser;
|
||||
userId: string | null;
|
||||
setDemoUser: (u: DemoUser) => void;
|
||||
};
|
||||
|
||||
const AuthContext = createContext<AuthContextValue>({ demoUser: null, userId: null, setDemoUser: () => {} });
|
||||
|
||||
export function useAuth() {
|
||||
return useContext(AuthContext);
|
||||
}
|
||||
|
||||
export function AuthProvider({ demoUser, tenantId, children }: { demoUser: DemoUser; tenantId: string; children: React.ReactNode }) {
|
||||
const [localDemoUser, setLocalDemoUser] = useState<DemoUser>(demoUser);
|
||||
const [userId, setUserId] = useState<string | null>(null);
|
||||
const ensureUser = useMutation(api.users.ensureUser);
|
||||
|
||||
useEffect(() => {
|
||||
async function run() {
|
||||
if (!process.env.NEXT_PUBLIC_CONVEX_URL) return; // allow dev without backend
|
||||
if (!localDemoUser) return;
|
||||
try {
|
||||
const user = await ensureUser({ tenantId, name: localDemoUser.name, email: localDemoUser.email, avatarUrl: localDemoUser.avatarUrl });
|
||||
// Convex returns a full document
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
setUserId((user as any)?._id ?? null);
|
||||
} catch (e) {
|
||||
console.error("Failed to ensure user:", e);
|
||||
}
|
||||
}
|
||||
run();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [localDemoUser?.email, tenantId]);
|
||||
|
||||
const value = useMemo(() => ({ demoUser: localDemoUser, setDemoUser: setLocalDemoUser, userId }), [localDemoUser, userId]);
|
||||
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue