feat: add AI Dental Shopping section with sidebar nav and Login Info page
- Add AI Dental Shopping to sidebar with Search/Tag and Login Info sub-pages - Build full-stack Login Info CRUD: save vendor name, website, username, password per user - Add ShoppingVendor Prisma model, run db push, regenerate client and Zod schemas - Add storage layer, REST API at /api/shopping-vendors/, and frontend table with add/edit/delete modal Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
import * as z from 'zod';
|
||||
export const ShoppingVendorAggregateResultSchema = z.object({ _count: z.object({
|
||||
id: z.number(),
|
||||
userId: z.number(),
|
||||
vendorName: z.number(),
|
||||
websiteUrl: z.number(),
|
||||
loginUsername: z.number(),
|
||||
loginPassword: z.number(),
|
||||
user: z.number()
|
||||
}).optional(),
|
||||
_sum: z.object({
|
||||
id: z.number().nullable(),
|
||||
userId: z.number().nullable()
|
||||
}).nullable().optional(),
|
||||
_avg: z.object({
|
||||
id: z.number().nullable(),
|
||||
userId: z.number().nullable()
|
||||
}).nullable().optional(),
|
||||
_min: z.object({
|
||||
id: z.number().int().nullable(),
|
||||
userId: z.number().int().nullable(),
|
||||
vendorName: z.string().nullable(),
|
||||
websiteUrl: z.string().nullable(),
|
||||
loginUsername: z.string().nullable(),
|
||||
loginPassword: z.string().nullable()
|
||||
}).nullable().optional(),
|
||||
_max: z.object({
|
||||
id: z.number().int().nullable(),
|
||||
userId: z.number().int().nullable(),
|
||||
vendorName: z.string().nullable(),
|
||||
websiteUrl: z.string().nullable(),
|
||||
loginUsername: z.string().nullable(),
|
||||
loginPassword: z.string().nullable()
|
||||
}).nullable().optional()});
|
||||
@@ -0,0 +1,2 @@
|
||||
import * as z from 'zod';
|
||||
export const ShoppingVendorCountResultSchema = z.number();
|
||||
@@ -0,0 +1,4 @@
|
||||
import * as z from 'zod';
|
||||
export const ShoppingVendorCreateManyResultSchema = z.object({
|
||||
count: z.number()
|
||||
});
|
||||
@@ -0,0 +1,10 @@
|
||||
import * as z from 'zod';
|
||||
export const ShoppingVendorCreateResultSchema = z.object({
|
||||
id: z.number().int(),
|
||||
userId: z.number().int(),
|
||||
vendorName: z.string(),
|
||||
websiteUrl: z.string(),
|
||||
loginUsername: z.string(),
|
||||
loginPassword: z.string(),
|
||||
user: z.unknown()
|
||||
});
|
||||
@@ -0,0 +1,4 @@
|
||||
import * as z from 'zod';
|
||||
export const ShoppingVendorDeleteManyResultSchema = z.object({
|
||||
count: z.number()
|
||||
});
|
||||
@@ -0,0 +1,10 @@
|
||||
import * as z from 'zod';
|
||||
export const ShoppingVendorDeleteResultSchema = z.nullable(z.object({
|
||||
id: z.number().int(),
|
||||
userId: z.number().int(),
|
||||
vendorName: z.string(),
|
||||
websiteUrl: z.string(),
|
||||
loginUsername: z.string(),
|
||||
loginPassword: z.string(),
|
||||
user: z.unknown()
|
||||
}));
|
||||
@@ -0,0 +1,10 @@
|
||||
import * as z from 'zod';
|
||||
export const ShoppingVendorFindFirstResultSchema = z.nullable(z.object({
|
||||
id: z.number().int(),
|
||||
userId: z.number().int(),
|
||||
vendorName: z.string(),
|
||||
websiteUrl: z.string(),
|
||||
loginUsername: z.string(),
|
||||
loginPassword: z.string(),
|
||||
user: z.unknown()
|
||||
}));
|
||||
@@ -0,0 +1,20 @@
|
||||
import * as z from 'zod';
|
||||
export const ShoppingVendorFindManyResultSchema = z.object({
|
||||
data: z.array(z.object({
|
||||
id: z.number().int(),
|
||||
userId: z.number().int(),
|
||||
vendorName: z.string(),
|
||||
websiteUrl: z.string(),
|
||||
loginUsername: z.string(),
|
||||
loginPassword: z.string(),
|
||||
user: z.unknown()
|
||||
})),
|
||||
pagination: z.object({
|
||||
page: z.number().int().min(1),
|
||||
pageSize: z.number().int().min(1),
|
||||
total: z.number().int().min(0),
|
||||
totalPages: z.number().int().min(0),
|
||||
hasNext: z.boolean(),
|
||||
hasPrev: z.boolean()
|
||||
})
|
||||
});
|
||||
@@ -0,0 +1,10 @@
|
||||
import * as z from 'zod';
|
||||
export const ShoppingVendorFindUniqueResultSchema = z.nullable(z.object({
|
||||
id: z.number().int(),
|
||||
userId: z.number().int(),
|
||||
vendorName: z.string(),
|
||||
websiteUrl: z.string(),
|
||||
loginUsername: z.string(),
|
||||
loginPassword: z.string(),
|
||||
user: z.unknown()
|
||||
}));
|
||||
@@ -0,0 +1,42 @@
|
||||
import * as z from 'zod';
|
||||
export const ShoppingVendorGroupByResultSchema = z.array(z.object({
|
||||
id: z.number().int(),
|
||||
userId: z.number().int(),
|
||||
vendorName: z.string(),
|
||||
websiteUrl: z.string(),
|
||||
loginUsername: z.string(),
|
||||
loginPassword: z.string(),
|
||||
_count: z.object({
|
||||
id: z.number(),
|
||||
userId: z.number(),
|
||||
vendorName: z.number(),
|
||||
websiteUrl: z.number(),
|
||||
loginUsername: z.number(),
|
||||
loginPassword: z.number(),
|
||||
user: z.number()
|
||||
}).optional(),
|
||||
_sum: z.object({
|
||||
id: z.number().nullable(),
|
||||
userId: z.number().nullable()
|
||||
}).nullable().optional(),
|
||||
_avg: z.object({
|
||||
id: z.number().nullable(),
|
||||
userId: z.number().nullable()
|
||||
}).nullable().optional(),
|
||||
_min: z.object({
|
||||
id: z.number().int().nullable(),
|
||||
userId: z.number().int().nullable(),
|
||||
vendorName: z.string().nullable(),
|
||||
websiteUrl: z.string().nullable(),
|
||||
loginUsername: z.string().nullable(),
|
||||
loginPassword: z.string().nullable()
|
||||
}).nullable().optional(),
|
||||
_max: z.object({
|
||||
id: z.number().int().nullable(),
|
||||
userId: z.number().int().nullable(),
|
||||
vendorName: z.string().nullable(),
|
||||
websiteUrl: z.string().nullable(),
|
||||
loginUsername: z.string().nullable(),
|
||||
loginPassword: z.string().nullable()
|
||||
}).nullable().optional()
|
||||
}));
|
||||
@@ -0,0 +1,4 @@
|
||||
import * as z from 'zod';
|
||||
export const ShoppingVendorUpdateManyResultSchema = z.object({
|
||||
count: z.number()
|
||||
});
|
||||
@@ -0,0 +1,10 @@
|
||||
import * as z from 'zod';
|
||||
export const ShoppingVendorUpdateResultSchema = z.nullable(z.object({
|
||||
id: z.number().int(),
|
||||
userId: z.number().int(),
|
||||
vendorName: z.string(),
|
||||
websiteUrl: z.string(),
|
||||
loginUsername: z.string(),
|
||||
loginPassword: z.string(),
|
||||
user: z.unknown()
|
||||
}));
|
||||
@@ -0,0 +1,10 @@
|
||||
import * as z from 'zod';
|
||||
export const ShoppingVendorUpsertResultSchema = z.object({
|
||||
id: z.number().int(),
|
||||
userId: z.number().int(),
|
||||
vendorName: z.string(),
|
||||
websiteUrl: z.string(),
|
||||
loginUsername: z.string(),
|
||||
loginPassword: z.string(),
|
||||
user: z.unknown()
|
||||
});
|
||||
@@ -11,6 +11,7 @@ export const UserAggregateResultSchema = z.object({ _count: z.object({
|
||||
npiProviders: z.number(),
|
||||
claims: z.number(),
|
||||
insuranceCredentials: z.number(),
|
||||
shoppingVendors: z.number(),
|
||||
updatedPayments: z.number(),
|
||||
backups: z.number(),
|
||||
backupDestinations: z.number(),
|
||||
|
||||
@@ -11,6 +11,7 @@ export const UserCreateResultSchema = z.object({
|
||||
npiProviders: z.array(z.unknown()),
|
||||
claims: z.array(z.unknown()),
|
||||
insuranceCredentials: z.array(z.unknown()),
|
||||
shoppingVendors: z.array(z.unknown()),
|
||||
updatedPayments: z.array(z.unknown()),
|
||||
backups: z.array(z.unknown()),
|
||||
backupDestinations: z.array(z.unknown()),
|
||||
|
||||
@@ -11,6 +11,7 @@ export const UserDeleteResultSchema = z.nullable(z.object({
|
||||
npiProviders: z.array(z.unknown()),
|
||||
claims: z.array(z.unknown()),
|
||||
insuranceCredentials: z.array(z.unknown()),
|
||||
shoppingVendors: z.array(z.unknown()),
|
||||
updatedPayments: z.array(z.unknown()),
|
||||
backups: z.array(z.unknown()),
|
||||
backupDestinations: z.array(z.unknown()),
|
||||
|
||||
@@ -11,6 +11,7 @@ export const UserFindFirstResultSchema = z.nullable(z.object({
|
||||
npiProviders: z.array(z.unknown()),
|
||||
claims: z.array(z.unknown()),
|
||||
insuranceCredentials: z.array(z.unknown()),
|
||||
shoppingVendors: z.array(z.unknown()),
|
||||
updatedPayments: z.array(z.unknown()),
|
||||
backups: z.array(z.unknown()),
|
||||
backupDestinations: z.array(z.unknown()),
|
||||
|
||||
@@ -12,6 +12,7 @@ export const UserFindManyResultSchema = z.object({
|
||||
npiProviders: z.array(z.unknown()),
|
||||
claims: z.array(z.unknown()),
|
||||
insuranceCredentials: z.array(z.unknown()),
|
||||
shoppingVendors: z.array(z.unknown()),
|
||||
updatedPayments: z.array(z.unknown()),
|
||||
backups: z.array(z.unknown()),
|
||||
backupDestinations: z.array(z.unknown()),
|
||||
|
||||
@@ -11,6 +11,7 @@ export const UserFindUniqueResultSchema = z.nullable(z.object({
|
||||
npiProviders: z.array(z.unknown()),
|
||||
claims: z.array(z.unknown()),
|
||||
insuranceCredentials: z.array(z.unknown()),
|
||||
shoppingVendors: z.array(z.unknown()),
|
||||
updatedPayments: z.array(z.unknown()),
|
||||
backups: z.array(z.unknown()),
|
||||
backupDestinations: z.array(z.unknown()),
|
||||
|
||||
@@ -17,6 +17,7 @@ export const UserGroupByResultSchema = z.array(z.object({
|
||||
npiProviders: z.number(),
|
||||
claims: z.number(),
|
||||
insuranceCredentials: z.number(),
|
||||
shoppingVendors: z.number(),
|
||||
updatedPayments: z.number(),
|
||||
backups: z.number(),
|
||||
backupDestinations: z.number(),
|
||||
|
||||
@@ -11,6 +11,7 @@ export const UserUpdateResultSchema = z.nullable(z.object({
|
||||
npiProviders: z.array(z.unknown()),
|
||||
claims: z.array(z.unknown()),
|
||||
insuranceCredentials: z.array(z.unknown()),
|
||||
shoppingVendors: z.array(z.unknown()),
|
||||
updatedPayments: z.array(z.unknown()),
|
||||
backups: z.array(z.unknown()),
|
||||
backupDestinations: z.array(z.unknown()),
|
||||
|
||||
@@ -11,6 +11,7 @@ export const UserUpsertResultSchema = z.object({
|
||||
npiProviders: z.array(z.unknown()),
|
||||
claims: z.array(z.unknown()),
|
||||
insuranceCredentials: z.array(z.unknown()),
|
||||
shoppingVendors: z.array(z.unknown()),
|
||||
updatedPayments: z.array(z.unknown()),
|
||||
backups: z.array(z.unknown()),
|
||||
backupDestinations: z.array(z.unknown()),
|
||||
|
||||
@@ -141,6 +141,19 @@ export { InsuranceCredentialDeleteManyResultSchema } from './InsuranceCredential
|
||||
export { InsuranceCredentialAggregateResultSchema } from './InsuranceCredentialAggregateResult.schema';
|
||||
export { InsuranceCredentialGroupByResultSchema } from './InsuranceCredentialGroupByResult.schema';
|
||||
export { InsuranceCredentialCountResultSchema } from './InsuranceCredentialCountResult.schema';
|
||||
export { ShoppingVendorFindUniqueResultSchema } from './ShoppingVendorFindUniqueResult.schema';
|
||||
export { ShoppingVendorFindFirstResultSchema } from './ShoppingVendorFindFirstResult.schema';
|
||||
export { ShoppingVendorFindManyResultSchema } from './ShoppingVendorFindManyResult.schema';
|
||||
export { ShoppingVendorCreateResultSchema } from './ShoppingVendorCreateResult.schema';
|
||||
export { ShoppingVendorCreateManyResultSchema } from './ShoppingVendorCreateManyResult.schema';
|
||||
export { ShoppingVendorUpdateResultSchema } from './ShoppingVendorUpdateResult.schema';
|
||||
export { ShoppingVendorUpdateManyResultSchema } from './ShoppingVendorUpdateManyResult.schema';
|
||||
export { ShoppingVendorUpsertResultSchema } from './ShoppingVendorUpsertResult.schema';
|
||||
export { ShoppingVendorDeleteResultSchema } from './ShoppingVendorDeleteResult.schema';
|
||||
export { ShoppingVendorDeleteManyResultSchema } from './ShoppingVendorDeleteManyResult.schema';
|
||||
export { ShoppingVendorAggregateResultSchema } from './ShoppingVendorAggregateResult.schema';
|
||||
export { ShoppingVendorGroupByResultSchema } from './ShoppingVendorGroupByResult.schema';
|
||||
export { ShoppingVendorCountResultSchema } from './ShoppingVendorCountResult.schema';
|
||||
export { PdfGroupFindUniqueResultSchema } from './PdfGroupFindUniqueResult.schema';
|
||||
export { PdfGroupFindFirstResultSchema } from './PdfGroupFindFirstResult.schema';
|
||||
export { PdfGroupFindManyResultSchema } from './PdfGroupFindManyResult.schema';
|
||||
|
||||
Reference in New Issue
Block a user