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:
esdrasrenan 2025-10-04 00:31:44 -03:00
parent 2230590e57
commit 27b103cb46
97 changed files with 15117 additions and 15715 deletions

View 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>;
}