diff --git a/web/src/actions/admin/service.ts b/web/src/actions/admin/service.ts index 3e0b2af..4ec6fd5 100644 --- a/web/src/actions/admin/service.ts +++ b/web/src/actions/admin/service.ts @@ -11,6 +11,7 @@ import { prisma } from '../../lib/prisma' import { separateServiceUrlsByType } from '../../lib/urls' import { imageFileSchema, + stringListOfContactMethodsSchema, stringListOfUrlsSchemaRequired, zodCohercedNumber, zodContactMethod, @@ -45,6 +46,7 @@ const serviceSchemaBase = z.object({ description: z.string().min(1), allServiceUrls: stringListOfUrlsSchemaRequired, tosUrls: stringListOfUrlsSchemaRequired, + contactMethods: stringListOfContactMethodsSchema, kycLevel: z.coerce.number().int().min(0).max(4), kycLevelClarification: z.nativeEnum(KycLevelClarification).optional().nullable().default(null), attributes: z.array(z.coerce.number().int().positive()), @@ -52,7 +54,7 @@ const serviceSchemaBase = z.object({ verificationStatus: z.nativeEnum(VerificationStatus), verificationSummary: z.string().optional().nullable().default(null), verificationProofMd: z.string().optional().nullable().default(null), - acceptedCurrencies: z.array(z.nativeEnum(Currency)), + acceptedCurrencies: z.array(z.nativeEnum(Currency)).min(1), referral: z .string() .regex(/^(\?\w+=.|\/.+)/, 'Referral must be a valid URL parameter or path, not a full URL') @@ -69,7 +71,6 @@ const serviceSchemaBase = z.object({ }), registeredCompanyName: z.string().trim().max(100).optional().nullable(), imageFile: imageFileSchema, - overallScore: zodCohercedNumber(z.number().int().min(0).max(10)).optional(), serviceVisibility: z.nativeEnum(ServiceVisibility), internalNote: z.string().optional(), strictCommentingEnabled: z.boolean().optional().default(false), @@ -144,7 +145,6 @@ export const adminServiceActions = { referral: input.referral || null, serviceVisibility: input.serviceVisibility, slug: input.slug, - overallScore: input.overallScore, categories: { connect: input.categories.map((id) => ({ id })), }, @@ -155,6 +155,11 @@ export const adminServiceActions = { }, })), }, + contactMethods: { + create: input.contactMethods.map((value) => ({ + value, + })), + }, imageUrl, internalNotes: input.internalNote ? { @@ -165,6 +170,8 @@ export const adminServiceActions = { } : undefined, operatingSince: input.operatingSince, + registrationCountryCode: input.registrationCountryCode ?? null, + registeredCompanyName: input.registeredCompanyName, }, select: { id: true, @@ -266,7 +273,6 @@ export const adminServiceActions = { referral: input.referral || null, serviceVisibility: input.serviceVisibility, slug: input.slug, - overallScore: input.overallScore, previousSlugs: existingService.slug !== input.slug ? { @@ -354,7 +360,6 @@ export const adminServiceActions = { await prisma.serviceContactMethod.delete({ where: { id: input.id }, }) - return { success: true } }, }), }, @@ -480,7 +485,6 @@ export const adminServiceActions = { input: evidenceImageDeleteSchema, handler: async (input) => { await deleteFileLocally(input.fileUrl) - return { success: true } }, }), }, diff --git a/web/src/pages/admin/services/new.astro b/web/src/pages/admin/services/new.astro index a0c0ab4..92c9a1c 100644 --- a/web/src/pages/admin/services/new.astro +++ b/web/src/pages/admin/services/new.astro @@ -1,24 +1,57 @@ --- -import { AttributeCategory, Currency, VerificationStatus } from '@prisma/client' -import { Icon } from 'astro-icon/components' +import { ServiceVisibility, VerificationStatus } from '@prisma/client' import { actions, isInputError } from 'astro:actions' +import { orderBy } from 'lodash-es' +import InputCardGroup from '../../../components/InputCardGroup.astro' import InputCheckbox from '../../../components/InputCheckbox.astro' +import InputCheckboxGroup from '../../../components/InputCheckboxGroup.astro' +import InputImageFile from '../../../components/InputImageFile.astro' +import InputSelect from '../../../components/InputSelect.astro' +import InputSubmitButton from '../../../components/InputSubmitButton.astro' +import InputText from '../../../components/InputText.astro' +import InputTextArea from '../../../components/InputTextArea.astro' +import { getAttributeCategoryInfo } from '../../../constants/attributeCategories' +import { getAttributeTypeInfo } from '../../../constants/attributeTypes' +import { contactMethodUrlTypes } from '../../../constants/contactMethods' +import { countries } from '../../../constants/countries' +import { currencies } from '../../../constants/currencies' +import { kycLevelClarifications } from '../../../constants/kycLevelClarifications' +import { kycLevels } from '../../../constants/kycLevels' +import { serviceVisibilities } from '../../../constants/serviceVisibility' +import { verificationStatuses } from '../../../constants/verificationStatus' import BaseLayout from '../../../layouts/BaseLayout.astro' -import { cn } from '../../../lib/cn' import { prisma } from '../../../lib/prisma' -const categories = await Astro.locals.banners.try('Failed to fetch categories', () => - prisma.category.findMany({ - orderBy: { name: 'asc' }, - }) -) - -const attributes = await Astro.locals.banners.try('Failed to fetch attributes', () => - prisma.attribute.findMany({ - orderBy: { category: 'asc' }, - }) -) +const [categories, attributes] = await Astro.locals.banners.tryMany([ + [ + 'Failed to fetch categories', + () => + prisma.category.findMany({ + orderBy: { name: 'asc' }, + select: { + id: true, + name: true, + icon: true, + }, + }), + [], + ], + [ + 'Failed to fetch attributes', + () => + prisma.attribute.findMany({ + orderBy: { category: 'asc' }, + select: { + id: true, + title: true, + category: true, + type: true, + }, + }), + [], + ], +]) const result = Astro.getActionResult(actions.admin.service.create) Astro.locals.banners.addIfSuccess(result, 'Service created successfully') @@ -28,382 +61,287 @@ if (result && !result.error) { const inputErrors = isInputError(result?.error) ? result.error.fields : {} --- - -
-
- service.create -
+ +

Create Service

-
-
- - - { - inputErrors.name && ( -

{inputErrors.name.join(', ')}

- ) - } -
+ + -
- -