feat: wire frontend pages to tRPC APIs

- Add hooks (useAuth, useSubscription, useNotifications) for real API data
- Add auth service (login/signup) with password hashing and session support
- Replace stub auth with real tRPC calls in login/signup/onboarding pages
- Replace mock dashboard data with real API data from hooks
- Create service pages: DarkWatch, VoicePrint, SpamShield, HomeTitle, RemoveBrokers, Settings
- Update Navbar, TopBar, Sidebar with real user data and correct routes
- Add passwordHash field to users schema for credential auth
- Fix tests to work with real hooks (mock tRPC/hooks)
This commit is contained in:
2026-05-25 17:34:48 -04:00
parent eb8e57c674
commit 7cbcde6a6b
46 changed files with 2418 additions and 418 deletions

View File

@@ -28,7 +28,7 @@ const mockRemoveMember = vi.mocked(removeMember);
const mockUpdateMemberRole = vi.mocked(updateMemberRole);
type User = {
id: string; email: string; name: string | null; image: string | null;
id: string; email: string; name: string | null; image: string | null; passwordHash: string | null;
role: "user" | "family_admin" | "family_member" | "support"; emailVerified: Date | null; deletedAt: Date | null;
stripeCustomerId: string | null;
createdAt: Date; updatedAt: Date;
@@ -96,7 +96,7 @@ function createCaller(user: User | null) {
}
const baseUser: User = {
id: "user-1", email: "a@b.com", name: "Test", image: null,
id: "user-1", email: "a@b.com", name: "Test", image: null, passwordHash: null,
role: "user", emailVerified: null, deletedAt: null,
stripeCustomerId: null,
createdAt: new Date(), updatedAt: new Date(),

View File

@@ -1,13 +1,14 @@
import { wrap } from "@typeschema/valibot";
import { object, string, minLength, email as emailVal } from "valibot";
import { TRPCError } from "@trpc/server";
import { createTRPCRouter, protectedProcedure } from "../utils";
import { createTRPCRouter, publicProcedure, protectedProcedure } from "../utils";
import {
UpdateUserSchema,
InviteMemberSchema,
RemoveMemberSchema,
UpdateRoleSchema,
} from "../schemas/user";
import { getUserById, updateUser, deleteUser } from "~/server/services/user.service";
import { getUserById, updateUser, deleteUser, createUserWithPassword, authenticateUser } from "~/server/services/user.service";
import {
getFamilyGroup,
inviteMember,
@@ -15,7 +16,33 @@ import {
updateMemberRole,
} from "~/server/services/family.service";
const LoginSchema = object({
email: string([emailVal()]),
password: string([minLength(1)]),
});
const SignupSchema = object({
name: string([minLength(1)]),
email: string([emailVal()]),
password: string([minLength(8)]),
});
export const userRouter = createTRPCRouter({
login: publicProcedure
.input(wrap(LoginSchema))
.mutation(async ({ input }) => {
return authenticateUser(input.email, input.password);
}),
signup: publicProcedure
.input(wrap(SignupSchema))
.mutation(async ({ input }) => {
const user = await createUserWithPassword(input.name, input.email, input.password);
const { createSession } = await import("~/server/auth/session");
const session = await createSession(user.id);
return { user, sessionToken: session.sessionToken };
}),
me: protectedProcedure.query(async ({ ctx }) => {
const user = await getUserById(ctx.user.id);
return user;