+
+
+
({
label: category.name,
@@ -286,77 +313,82 @@ const errorTextClasses = 'mt-1 text-xs text-red-400'
selectedValues={service.categories.map((c) => c.id.toString())}
error={serviceInputErrors.categories}
/>
-
-
- ({
- label: `${kycLevel.name} (${kycLevel.value}/4)`,
- value: kycLevel.id.toString(),
- icon: kycLevel.icon,
- description: kycLevel.description,
- }))}
- selectedValue={service.kycLevel.toString()}
- iconSize="md"
- cardSize="md"
- error={serviceInputErrors.kycLevel}
- class="[&>div]:grid-cols-2 [&>div]:[--card-min-size:16rem]"
- />
-
-
-
({
- label: `${attribute.title} (${attribute.category})`,
- value: attribute.id.toString(),
- }))}
+ size="lg"
+ options={orderBy(
+ attributes.map((attribute) => ({
+ ...attribute,
+ categoryInfo: getAttributeCategoryInfo(attribute.category),
+ typeInfo: getAttributeTypeInfo(attribute.type),
+ })),
+ ['categoryInfo.order', 'typeInfo.order']
+ ).map((attribute) => {
+ return {
+ label: attribute.title,
+ value: attribute.id.toString(),
+ icon: [attribute.categoryInfo.icon, attribute.typeInfo.icon],
+ iconClassName: [attribute.categoryInfo.classNames.icon, attribute.typeInfo.classNames.icon],
+ }
+ })}
selectedValues={service.attributes.map((a) => a.attribute.id.toString())}
error={serviceInputErrors.attributes}
/>
-
- ({
- label: status.label,
- value: status.value,
- icon: status.icon,
- iconClass: status.classNames.icon,
- description: status.description,
- }))}
- selectedValue={service.verificationStatus}
- error={serviceInputErrors.verificationStatus}
- cardSize="md"
- iconSize="md"
- class="[&>div]:grid-cols-2 [&>div]:[--card-min-size:16rem]"
- />
-
+
({
+ label: `${kycLevel.name} (${kycLevel.value}/4)`,
+ value: kycLevel.id.toString(),
+ icon: kycLevel.icon,
+ description: kycLevel.description,
+ }))}
+ selectedValue={service.kycLevel.toString()}
+ iconSize="md"
+ cardSize="md"
+ error={serviceInputErrors.kycLevel}
+ class="[&>div]:grid-cols-2 [&>div]:[--card-min-size:16rem]"
+ />
-
- ({
- label: currency.name,
- value: currency.id,
- icon: currency.icon,
- }))}
- selectedValue={service.acceptedCurrencies}
- error={serviceInputErrors.acceptedCurrencies}
- required
- multiple
- />
-
+ ({
+ label: status.label,
+ value: status.value,
+ icon: status.icon,
+ iconClass: status.classNames.icon,
+ description: status.description,
+ }))}
+ selectedValue={service.verificationStatus}
+ error={serviceInputErrors.verificationStatus}
+ cardSize="sm"
+ iconSize="sm"
+ class="[&>div]:grid-cols-2 [&>div]:[--card-min-size:16rem]"
+ />
-
+
({
+ label: currency.name,
+ value: currency.id,
+ icon: currency.icon,
+ }))}
+ selectedValue={service.acceptedCurrencies}
+ error={serviceInputErrors.acceptedCurrencies}
+ required
+ multiple
+ />
+
+
-
-
-
-
-
+ ({
+ label: visibility.label,
+ value: visibility.value,
+ icon: visibility.icon,
+ iconClass: visibility.iconClass,
+ description: visibility.description,
+ }))}
+ selectedValue={service.serviceVisibility}
+ error={serviceInputErrors.serviceVisibility}
+ cardSize="sm"
+ />
-
- ({
- label: visibility.label,
- value: visibility.value,
- icon: visibility.icon,
- iconClass: visibility.iconClass,
- description: visibility.description,
- }))}
- selectedValue={service.serviceVisibility}
- error={serviceInputErrors.serviceVisibility}
- cardSize="sm"
- />
-
-
-
+
-
+
-
-
-
- Events
-
-
-
+
+
{
- service.events.length > 0 && (
-
-
Existing Events
- {service.events.map((event) => (
-
-
-
-
- {event.title}
-
- {event.type}
-
- {!event.visible && (
-
- Hidden
-
- )}
-
-
{event.content}
-
- Started: {new Date(event.startedAt).toLocaleDateString()}
-
- Ended:
- {event.endedAt
- ? event.endedAt === event.startedAt
- ? '1-time event'
- : new Date(event.endedAt).toLocaleDateString()
- : 'Ongoing'}
-
- {event.source && Source: {event.source}}
-
-
-
-
-
-
-
-
- {/* Edit Event Form - Hidden by default */}
-
-
- ))}
-
- )
- }
-
-
-
-
-
- Add New Event
-
-
-
-
-
-
-
-
-
-
- Verification Steps
-
-
-
- {
- service.verificationSteps.length > 0 && (
-
-
Submitted Steps
- {service.verificationSteps.map((step) => (
-
-
-
-
- {step.title}
-
- {step.status.replace('_', ' ')}
-
-
-
{step.description}
- {step.evidenceMd && (
-
Evidence provided (see edit form)
- )}
-
- Created: {new Date(step.createdAt).toLocaleDateString()}
-
-
-
-
-
-
-
-
- {/* Edit Verification Step Form - Hidden by default */}
-
-
- ))}
-
- )
- }
-
-
-
-
-
- Add New Verification Step
-
-
-
-
-
-
-
-
-
- Verification Requests
-
- {service._count.verificationRequests}
-
-
-
- {
- service.verificationRequests.length > 0 ? (
-
-
-
-
- | User |
- Requested At |
-
-
-
- {service.verificationRequests.map((request) => (
-
- |
-
- |
- {new Date(request.createdAt).toLocaleString()} |
-
- ))}
-
-
-
+ service.events.length === 0 ? (
+
+ No events yet.
+
) : (
-
No verification requests yet.
- )
- }
-
-
-
-
-
-
- Contact Methods
-
-
-
- {
- service.contactMethods.length > 0 && (
-
-
Existing Contact Methods
- {service.contactMethods.map((method) => {
- const contactMethodInfo = formatContactMethod(method.value)
+
+ {service.events.map((event) => {
+ const eventTypeInfo = getEventTypeInfo(event.type)
return (
-
+
-
- {contactMethodInfo.label}
+ {event.title}
+
+ {!event.visible && (
+
+ )}
-
- {method.label ?? contactMethodInfo.formattedValue}{' '}
- ({method.value})
+
{event.content}
+
+ Started: {new Date(event.startedAt).toLocaleDateString()}
+
+ Ended:
+ {event.endedAt
+ ? event.endedAt === event.startedAt
+ ? '1-time event'
+ : new Date(event.endedAt).toLocaleDateString()
+ : 'Ongoing'}
+
+ {event.source && Source: {event.source}}
+
+
+
+
+
+
+
+
+ {/* Edit Event Form - Hidden by default */}
+
+
+ )
+ })}
+
+ )
+ }
+
+
+
+
+
+
+
+
+
+ {
+ service.verificationSteps.length === 0 ? (
+
+ No verification steps yet.
+
+ ) : (
+
+ {service.verificationSteps.map((step) => {
+ const verificationStepStatusInfo = getVerificationStepStatusInfo(step.status)
+ return (
+
+
+
+
+ {step.title}
+
+
+
{step.description}
+ {step.evidenceMd && (
+
Evidence provided (see edit form)
+ )}
+
+ Created: {new Date(step.createdAt).toLocaleDateString()}
-
+
+
+
+
+ {/* Edit Verification Step Form - Hidden by default */}
+
+
+ )
+ })}
+
+ )
+ }
+
+
+
+
+
+
+
+
+ {
+ service.verificationRequests.length > 0 ? (
+
+
+
+
+ | User |
+ Requested |
+
+
+
+ {service.verificationRequests.map((request) => (
+
+ |
+
+ |
+
+
+ |
+
+ ))}
+
+
+
+ ) : (
+
+ No verification requests yet.
+
+ )
+ }
+
+
+
+
+ {
+ service.contactMethods.length === 0 ? (
+
+ No contact methods yet.
+
+ ) : (
+
+ {service.contactMethods.map((method) => {
+ const contactMethodInfo = formatContactMethod(method.value)
+ return (
+
+
+
+
+
+
+ {method.label ?? contactMethodInfo.formattedValue}
+
+
+
{method.value}
+
+
+
+
@@ -1049,49 +859,30 @@ const errorTextClasses = 'mt-1 text-xs text-red-400'
id={`edit-contact-method-${method.id}`}
method="POST"
action={actions.admin.service.updateContactMethod}
- class="mt-3 hidden space-y-3 rounded-md border border-zinc-600 bg-zinc-700/40 p-3"
+ class="border-night-500 bg-night-700 mt-3 hidden space-y-3 rounded-md border p-3"
>
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
)
@@ -1099,45 +890,27 @@ const errorTextClasses = 'mt-1 text-xs text-red-400'
)
}
+
-
-
-
-
- Add New Contact Method
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
diff --git a/web/src/pages/admin/users/[username].astro b/web/src/pages/admin/users/[username].astro
index 680b1ea..2b48cc4 100644
--- a/web/src/pages/admin/users/[username].astro
+++ b/web/src/pages/admin/users/[username].astro
@@ -4,6 +4,7 @@ import { actions, isInputError } from 'astro:actions'
import BadgeSmall from '../../../components/BadgeSmall.astro'
import Button from '../../../components/Button.astro'
+import FormSection from '../../../components/FormSection.astro'
import InputCardGroup from '../../../components/InputCardGroup.astro'
import InputImageFile from '../../../components/InputImageFile.astro'
import InputSelect from '../../../components/InputSelect.astro'
@@ -171,90 +172,88 @@ if (!user) return Astro.rewrite('/404')