diff --git a/web/scripts/faker.ts b/web/scripts/faker.ts index f13c83f..b6ddcc0 100755 --- a/web/scripts/faker.ts +++ b/web/scripts/faker.ts @@ -650,22 +650,22 @@ const generateFakeService = (users: User[]) => { status === 'VERIFICATION_SUCCESS' || status === 'VERIFICATION_FAILED' ? faker.lorem.paragraphs() : null, referral: `?ref=${faker.string.alphanumeric(6)}`, acceptedCurrencies: faker.helpers.arrayElements(Object.values(Currency), { min: 1, max: 5 }), - serviceUrls: Array.from({ length: faker.number.int({ min: 1, max: 3 }) }, () => faker.internet.url()), - tosUrls: Array.from({ length: faker.number.int({ min: 0, max: 2 }) }, () => faker.internet.url()), - onionUrls: Array.from( - { length: faker.number.int({ min: 0, max: 2 }) }, - () => `http://${faker.string.alphanumeric({ length: 56, casing: 'lower' })}.onion` + serviceUrls: faker.helpers.multiple(() => faker.internet.url(), { count: { min: 1, max: 3 } }), + tosUrls: faker.helpers.multiple(() => faker.internet.url(), { count: { min: 1, max: 2 } }), + onionUrls: faker.helpers.multiple( + () => `http://${faker.string.alphanumeric({ length: 56, casing: 'lower' })}.onion`, + { count: { min: 0, max: 2 } } ), - i2pUrls: Array.from( - { length: faker.number.int({ min: 0, max: 2 }) }, - () => `http://${faker.string.alphanumeric({ length: 52, casing: 'lower' })}.b32.i2p` + i2pUrls: faker.helpers.multiple( + () => `http://${faker.string.alphanumeric({ length: 52, casing: 'lower' })}.b32.i2p`, + { count: { min: 0, max: 2 } } ), imageUrl: `https://ui-avatars.com/api/?name=${encodeURIComponent(name)}&background=random&format=svg`, listedAt: faker.date.past(), verifiedAt: status === VerificationStatus.VERIFICATION_SUCCESS ? faker.date.past() : null, tosReview: faker.helpers.arrayElement(tosReviewExamples), tosReviewAt: faker.date.past(), - userSentiment: Math.random() > 0.2 ? generateFakeUserSentiment() : undefined, + userSentiment: faker.helpers.maybe(() => generateFakeUserSentiment(), { probability: 0.8 }), userSentimentAt: faker.date.recent(), } as const satisfies Prisma.ServiceCreateInput } diff --git a/web/src/actions/admin/service.ts b/web/src/actions/admin/service.ts index 19705ff..8c196e3 100644 --- a/web/src/actions/admin/service.ts +++ b/web/src/actions/admin/service.ts @@ -106,9 +106,13 @@ export const adminServiceActions = { update: defineProtectedAction({ accept: 'form', permissions: 'admin', - input: serviceSchemaBase.transform(addSlugIfMissing), + input: serviceSchemaBase + .extend({ + removeImage: z.boolean().optional(), + }) + .transform(addSlugIfMissing), handler: async (input) => { - const { id, categories, attributes, imageFile, ...data } = input + const { id, categories, attributes, imageFile, removeImage, ...data } = input const existing = await prisma.service.findUnique({ where: { @@ -124,7 +128,11 @@ export const adminServiceActions = { }) } - const imageUrl = imageFile ? await saveFileLocally(imageFile, imageFile.name) : undefined + const imageUrl = removeImage + ? null + : imageFile + ? await saveFileLocally(imageFile, imageFile.name) + : undefined // Get existing attributes and categories to compute differences const existingService = await prisma.service.findUnique({ diff --git a/web/src/components/InputCheckboxGroup.astro b/web/src/components/InputCheckboxGroup.astro index a39d262..574d24d 100644 --- a/web/src/components/InputCheckboxGroup.astro +++ b/web/src/components/InputCheckboxGroup.astro @@ -54,9 +54,9 @@ const hasError = !!wrapperProps.error && wrapperProps.error.length > 0 disabled={disabled} /> {icons.map((icon, index) => ( - + ))} - {option.label} + {option.label} ) }) diff --git a/web/src/components/InputFile.astro b/web/src/components/InputFile.astro index 848f3b4..e8e649d 100644 --- a/web/src/components/InputFile.astro +++ b/web/src/components/InputFile.astro @@ -16,13 +16,20 @@ type Props = Omit, 'children' | 'inputId'> & } } -const { accept, disabled, multiple, removeCheckbox, ...wrapperProps } = Astro.props +const { accept, disabled, multiple, removeCheckbox, classNames, ...wrapperProps } = Astro.props const inputId = Astro.locals.makeId(`input-${wrapperProps.name}`) const hasError = !!wrapperProps.error && wrapperProps.error.length > 0 --- - + { !!removeCheckbox && (