Release 2025-05-25-irZj
This commit is contained in:
@@ -12,7 +12,7 @@
|
||||
"db-push": "prisma migrate dev",
|
||||
"db-triggers": "just import-triggers",
|
||||
"db-update": "prisma migrate dev && just import-triggers",
|
||||
"db-reset": "prisma migrate reset && prisma migrate dev && just import-triggers && tsx scripts/faker.ts",
|
||||
"db-reset": "prisma migrate reset -f && prisma migrate dev && just import-triggers && tsx scripts/faker.ts",
|
||||
"db-fill": "tsx scripts/faker.ts",
|
||||
"db-fill-clean": "tsx scripts/faker.ts --cleanup",
|
||||
"format": "prettier --write .",
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
-- AlterEnum
|
||||
ALTER TYPE "ServiceVisibility" ADD VALUE 'ARCHIVED';
|
||||
@@ -87,6 +87,7 @@ enum ServiceVisibility {
|
||||
PUBLIC
|
||||
UNLISTED
|
||||
HIDDEN
|
||||
ARCHIVED
|
||||
}
|
||||
|
||||
enum Currency {
|
||||
|
||||
@@ -2,19 +2,20 @@ import crypto from 'crypto'
|
||||
|
||||
import { faker } from '@faker-js/faker'
|
||||
import {
|
||||
AnnouncementType,
|
||||
AttributeCategory,
|
||||
AttributeType,
|
||||
CommentStatus,
|
||||
Currency,
|
||||
EventType,
|
||||
PrismaClient,
|
||||
ServiceSuggestionStatus,
|
||||
ServiceSuggestionType,
|
||||
ServiceUserRole,
|
||||
VerificationStatus,
|
||||
type Prisma,
|
||||
EventType,
|
||||
type User,
|
||||
ServiceUserRole,
|
||||
AnnouncementType,
|
||||
type ServiceVisibility,
|
||||
} from '@prisma/client'
|
||||
import { uniqBy } from 'lodash-es'
|
||||
import { generateUsername } from 'unique-username-generator'
|
||||
@@ -611,7 +612,12 @@ const generateFakeEvent = (serviceId: number) => {
|
||||
}
|
||||
|
||||
const generateFakeService = (users: User[]) => {
|
||||
const status = faker.helpers.arrayElement(Object.values(VerificationStatus))
|
||||
const status = faker.helpers.weightedArrayElement<VerificationStatus>([
|
||||
{ weight: 20, value: 'VERIFICATION_SUCCESS' },
|
||||
{ weight: 30, value: 'APPROVED' },
|
||||
{ weight: 40, value: 'COMMUNITY_CONTRIBUTED' },
|
||||
{ weight: 10, value: 'VERIFICATION_FAILED' },
|
||||
])
|
||||
const name = faker.helpers.arrayElement(serviceNames)
|
||||
const slug = `${faker.helpers.slugify(name).toLowerCase()}-${faker.string.alphanumeric({ length: 6, casing: 'lower' })}`
|
||||
|
||||
@@ -623,6 +629,12 @@ const generateFakeService = (users: User[]) => {
|
||||
overallScore: 0,
|
||||
privacyScore: 0,
|
||||
trustScore: 0,
|
||||
serviceVisibility: faker.helpers.weightedArrayElement<ServiceVisibility>([
|
||||
{ weight: 80, value: 'PUBLIC' },
|
||||
{ weight: 10, value: 'UNLISTED' },
|
||||
{ weight: 5, value: 'HIDDEN' },
|
||||
{ weight: 5, value: 'ARCHIVED' },
|
||||
]),
|
||||
verificationStatus: status,
|
||||
verificationSummary:
|
||||
status === 'VERIFICATION_SUCCESS' || status === 'VERIFICATION_FAILED' ? faker.lorem.paragraph() : null,
|
||||
|
||||
@@ -150,7 +150,7 @@ const commentUrl = makeCommentUrl({ serviceSlug, commentId: comment.id, origin:
|
||||
checked={comment.suspicious}
|
||||
/>
|
||||
|
||||
<div class="comment-header flex items-center gap-2 text-sm">
|
||||
<div class="comment-header scrollbar-w-none flex items-center gap-2 overflow-auto text-sm">
|
||||
<label for={`collapse-${comment.id.toString()}`} class="cursor-pointer text-zinc-500 hover:text-zinc-300">
|
||||
<span class="collapse-symbol text-xs"></span>
|
||||
<span class="sr-only">Toggle comment visibility</span>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import { Icon } from 'astro-icon/components'
|
||||
|
||||
import { currencies } from '../constants/currencies'
|
||||
import { serviceVisibilitiesById } from '../constants/serviceVisibility'
|
||||
import { verificationStatusesByValue } from '../constants/verificationStatus'
|
||||
import { cn } from '../lib/cn'
|
||||
import { makeOverallScoreInfo } from '../lib/overallScore'
|
||||
@@ -25,6 +26,7 @@ type Props = HTMLAttributes<'a'> & {
|
||||
kycLevel: true
|
||||
imageUrl: true
|
||||
verificationStatus: true
|
||||
serviceVisibility: true
|
||||
acceptedCurrencies: true
|
||||
categories: {
|
||||
select: {
|
||||
@@ -43,11 +45,11 @@ const {
|
||||
slug,
|
||||
description,
|
||||
overallScore,
|
||||
|
||||
kycLevel,
|
||||
imageUrl,
|
||||
categories,
|
||||
verificationStatus,
|
||||
serviceVisibility,
|
||||
acceptedCurrencies,
|
||||
},
|
||||
class: className,
|
||||
@@ -69,7 +71,9 @@ const overallScoreInfo = makeOverallScoreInfo(overallScore)
|
||||
href={Element === 'a' ? `/service/${slug}` : undefined}
|
||||
{...aProps}
|
||||
class={cn(
|
||||
'border-night-600 bg-night-800 flex flex-col gap-(--gap) rounded-xl border p-(--gap) [--gap:calc(var(--spacing)*3)]',
|
||||
'border-night-600 group/card bg-night-800 flex flex-col gap-(--gap) rounded-xl border p-(--gap) [--gap:calc(var(--spacing)*3)]',
|
||||
(serviceVisibility === 'ARCHIVED' || verificationStatus === 'VERIFICATION_FAILED') &&
|
||||
'opacity-75 transition-opacity hover:opacity-100 focus-visible:opacity-100',
|
||||
className
|
||||
)}
|
||||
>
|
||||
@@ -79,7 +83,11 @@ const overallScoreInfo = makeOverallScoreInfo(overallScore)
|
||||
src={imageUrl}
|
||||
fallback="service"
|
||||
alt={name || 'Service logo'}
|
||||
class="size-12 shrink-0 rounded-sm object-contain text-white"
|
||||
class={cn(
|
||||
'size-12 shrink-0 rounded-sm object-contain text-white',
|
||||
(serviceVisibility === 'ARCHIVED' || verificationStatus === 'VERIFICATION_FAILED') &&
|
||||
'grayscale-67 transition-all group-hover/card:grayscale-0 group-focus-visible/card:grayscale-0'
|
||||
)}
|
||||
width={48}
|
||||
height={48}
|
||||
/>
|
||||
@@ -110,6 +118,23 @@ const overallScoreInfo = makeOverallScoreInfo(overallScore)
|
||||
]}
|
||||
</Tooltip>
|
||||
)
|
||||
}{
|
||||
serviceVisibility === 'ARCHIVED' && (
|
||||
<Tooltip
|
||||
text={serviceVisibilitiesById.ARCHIVED.label}
|
||||
position="right"
|
||||
class="-my-2 shrink-0 whitespace-nowrap"
|
||||
>
|
||||
<Icon
|
||||
is:inline={inlineIcons}
|
||||
name={serviceVisibilitiesById.ARCHIVED.icon}
|
||||
class={cn(
|
||||
'inline-block size-6 shrink-0 rounded-lg p-1 align-[-0.37em]',
|
||||
serviceVisibilitiesById.ARCHIVED.iconClass
|
||||
)}
|
||||
/>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
</h3>
|
||||
<div class="max-h-2 flex-1"></div>
|
||||
|
||||
@@ -8,6 +8,7 @@ type ServiceVisibilityInfo<T extends string | null | undefined = string> = {
|
||||
slug: string
|
||||
label: string
|
||||
description: string
|
||||
longDescription: string
|
||||
icon: string
|
||||
iconClass: string
|
||||
}
|
||||
@@ -28,6 +29,7 @@ export const {
|
||||
slug: value ? value.toLowerCase() : '',
|
||||
label: value ? transformCase(value, 'title') : String(value),
|
||||
description: '',
|
||||
longDescription: '',
|
||||
icon: 'ri:eye-line',
|
||||
iconClass: 'text-current/60',
|
||||
}),
|
||||
@@ -37,6 +39,7 @@ export const {
|
||||
slug: 'public',
|
||||
label: 'Public',
|
||||
description: 'Listed in search and browse.',
|
||||
longDescription: 'Listed in search and browse.',
|
||||
icon: 'ri:global-line',
|
||||
iconClass: 'text-green-500',
|
||||
},
|
||||
@@ -45,6 +48,7 @@ export const {
|
||||
slug: 'unlisted',
|
||||
label: 'Unlisted',
|
||||
description: 'Only accessible via direct link.',
|
||||
longDescription: "Unlisted service, only accessible via direct link and won't appear in searches.",
|
||||
icon: 'ri:link',
|
||||
iconClass: 'text-yellow-500',
|
||||
},
|
||||
@@ -53,8 +57,19 @@ export const {
|
||||
slug: 'hidden',
|
||||
label: 'Hidden',
|
||||
description: 'Only visible to moderators.',
|
||||
longDescription: 'Hidden service, only visible to moderators.',
|
||||
icon: 'ri:lock-line',
|
||||
iconClass: 'text-red-500',
|
||||
},
|
||||
{
|
||||
value: 'ARCHIVED',
|
||||
slug: 'archived',
|
||||
label: 'Archived',
|
||||
description: 'Service no longer exists or ceased operations.',
|
||||
longDescription:
|
||||
'This service has been archived and no longer exists or ceased operations. Information may be outdated.',
|
||||
icon: 'ri:archive-line',
|
||||
iconClass: 'text-day-100',
|
||||
},
|
||||
] as const satisfies ServiceVisibilityInfo<ServiceVisibility>[]
|
||||
)
|
||||
|
||||
@@ -2,6 +2,7 @@ import { orderBy } from 'lodash-es'
|
||||
|
||||
import { getAttributeCategoryInfo } from '../constants/attributeCategories'
|
||||
import { getAttributeTypeInfo } from '../constants/attributeTypes'
|
||||
import { serviceVisibilitiesById } from '../constants/serviceVisibility'
|
||||
import { READ_MORE_SENTENCE_LINK, verificationStatusesByValue } from '../constants/verificationStatus'
|
||||
|
||||
import { formatDateShort } from './timeAgo'
|
||||
@@ -36,6 +37,7 @@ export function makeNonDbAttributes(
|
||||
service: Prisma.ServiceGetPayload<{
|
||||
select: {
|
||||
verificationStatus: true
|
||||
serviceVisibility: true
|
||||
isRecentlyListed: true
|
||||
listedAt: true
|
||||
createdAt: true
|
||||
@@ -134,6 +136,16 @@ export function makeNonDbAttributes(
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: serviceVisibilitiesById.ARCHIVED.label,
|
||||
show: service.serviceVisibility === 'ARCHIVED',
|
||||
type: 'WARNING',
|
||||
category: 'TRUST',
|
||||
description: serviceVisibilitiesById.ARCHIVED.longDescription,
|
||||
privacyPoints: 0,
|
||||
trustPoints: 0,
|
||||
links: [],
|
||||
},
|
||||
{
|
||||
title: 'Recently listed',
|
||||
show: service.isRecentlyListed,
|
||||
|
||||
@@ -478,28 +478,43 @@ if (!service) return Astro.rewrite('/404')
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex shrink-0 gap-1.5">
|
||||
<form method="POST" action={actions.admin.event.toggle} class="contents">
|
||||
<input type="hidden" name="eventId" value={event.id} />
|
||||
<Tooltip text={event.visible ? 'Hide Event' : 'Show Event'}>
|
||||
<Tooltip text={event.visible ? 'Hide' : 'Show'}>
|
||||
<form method="POST" action={actions.admin.event.toggle} class="contents">
|
||||
<input type="hidden" name="eventId" value={event.id} />
|
||||
<Button
|
||||
type="submit"
|
||||
variant="faded"
|
||||
size="sm"
|
||||
icon={event.visible ? 'ri:eye-off-line' : 'ri:eye-line'}
|
||||
iconOnly
|
||||
label={event.visible ? 'Hide' : 'Show'}
|
||||
/>
|
||||
</Tooltip>
|
||||
</form>
|
||||
<Button
|
||||
type="button"
|
||||
variant="faded"
|
||||
size="sm"
|
||||
icon="ri:pencil-line"
|
||||
onclick={`document.getElementById('edit-event-${event.id}')?.classList.toggle('hidden')`}
|
||||
/>
|
||||
<form method="POST" action={actions.admin.event.delete} class="contents">
|
||||
<input type="hidden" name="eventId" value={event.id} />
|
||||
<Button type="submit" size="sm" variant="faded" icon="ri:delete-bin-line" />
|
||||
</form>
|
||||
</form>
|
||||
</Tooltip>
|
||||
<Tooltip text="Edit">
|
||||
<Button
|
||||
type="button"
|
||||
variant="faded"
|
||||
size="sm"
|
||||
icon="ri:pencil-line"
|
||||
onclick={`document.getElementById('edit-event-${event.id}')?.classList.toggle('hidden')`}
|
||||
iconOnly
|
||||
label="Edit"
|
||||
/>
|
||||
</Tooltip>
|
||||
<Tooltip text="Delete">
|
||||
<form method="POST" action={actions.admin.event.delete} class="contents">
|
||||
<input type="hidden" name="eventId" value={event.id} />
|
||||
<Button
|
||||
type="submit"
|
||||
size="sm"
|
||||
variant="faded"
|
||||
icon="ri:delete-bin-line"
|
||||
iconOnly
|
||||
label="Delete"
|
||||
/>
|
||||
</form>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
{/* Edit Event Form - Hidden by default */}
|
||||
@@ -673,17 +688,30 @@ if (!service) return Astro.rewrite('/404')
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex shrink-0 gap-1.5">
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
variant="faded"
|
||||
icon="ri:pencil-line"
|
||||
onclick={`document.getElementById('edit-verification-step-${step.id}')?.classList.toggle('hidden')`}
|
||||
/>
|
||||
<form method="POST" action={actions.admin.verificationStep.delete} class="inline">
|
||||
<input type="hidden" name="id" value={step.id} />
|
||||
<Button type="submit" size="sm" variant="faded" icon="ri:delete-bin-line" />
|
||||
</form>
|
||||
<Tooltip text="Edit">
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
variant="faded"
|
||||
icon="ri:pencil-line"
|
||||
onclick={`document.getElementById('edit-verification-step-${step.id}')?.classList.toggle('hidden')`}
|
||||
iconOnly
|
||||
label="Edit"
|
||||
/>
|
||||
</Tooltip>
|
||||
<Tooltip text="Delete">
|
||||
<form method="POST" action={actions.admin.verificationStep.delete} class="inline">
|
||||
<input type="hidden" name="id" value={step.id} />
|
||||
<Button
|
||||
type="submit"
|
||||
size="sm"
|
||||
variant="faded"
|
||||
icon="ri:delete-bin-line"
|
||||
iconOnly
|
||||
label="Delete"
|
||||
/>
|
||||
</form>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -844,21 +872,34 @@ if (!service) return Astro.rewrite('/404')
|
||||
<p class="text-day-400 text-sm text-pretty">{method.value}</p>
|
||||
</div>
|
||||
<div class="flex shrink-0 gap-1.5">
|
||||
<Button
|
||||
type="button"
|
||||
variant="faded"
|
||||
size="sm"
|
||||
icon="ri:pencil-line"
|
||||
onclick={`document.getElementById('edit-contact-method-${method.id}')?.classList.toggle('hidden')`}
|
||||
/>
|
||||
<form
|
||||
method="POST"
|
||||
action={actions.admin.service.deleteContactMethod}
|
||||
class="contents"
|
||||
>
|
||||
<input type="hidden" name="id" value={method.id} />
|
||||
<Button type="submit" size="sm" variant="faded" icon="ri:delete-bin-line" />
|
||||
</form>
|
||||
<Tooltip text="Edit">
|
||||
<Button
|
||||
type="button"
|
||||
variant="faded"
|
||||
size="sm"
|
||||
icon="ri:pencil-line"
|
||||
onclick={`document.getElementById('edit-contact-method-${method.id}')?.classList.toggle('hidden')`}
|
||||
iconOnly
|
||||
label="Edit"
|
||||
/>
|
||||
</Tooltip>
|
||||
<Tooltip text="Delete">
|
||||
<form
|
||||
method="POST"
|
||||
action={actions.admin.service.deleteContactMethod}
|
||||
class="contents"
|
||||
>
|
||||
<input type="hidden" name="id" value={method.id} />
|
||||
<Button
|
||||
type="submit"
|
||||
size="sm"
|
||||
variant="faded"
|
||||
icon="ri:delete-bin-line"
|
||||
iconOnly
|
||||
label="Delete"
|
||||
/>
|
||||
</form>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -8,7 +8,8 @@ import MyPicture from '../../../components/MyPicture.astro'
|
||||
import SortArrowIcon from '../../../components/SortArrowIcon.astro'
|
||||
import Tooltip from '../../../components/Tooltip.astro'
|
||||
import { getKycLevelInfo } from '../../../constants/kycLevels'
|
||||
import { getVerificationStatusInfo } from '../../../constants/verificationStatus'
|
||||
import { serviceVisibilities } from '../../../constants/serviceVisibility'
|
||||
import { getVerificationStatusInfo, verificationStatuses } from '../../../constants/verificationStatus'
|
||||
import BaseLayout from '../../../layouts/BaseLayout.astro'
|
||||
import { cn } from '../../../lib/cn'
|
||||
import { zodParseQueryParamsStoringErrors } from '../../../lib/parseUrlFilters'
|
||||
@@ -209,11 +210,11 @@ const truncate = (text: string, length: number) => {
|
||||
id="visibility"
|
||||
class="mt-1 w-full rounded-md border border-zinc-700 bg-zinc-900 px-3 py-2 text-sm text-zinc-200 focus:border-blue-500 focus:ring-blue-500 focus:outline-none"
|
||||
>
|
||||
<option value="">All Visibilities</option>
|
||||
<option value="">All</option>
|
||||
{
|
||||
Object.values(ServiceVisibility).map((status) => (
|
||||
<option value={status} selected={filters.visibility === status}>
|
||||
{status}
|
||||
serviceVisibilities.map((visibility) => (
|
||||
<option value={visibility.value} selected={filters.visibility === visibility.value}>
|
||||
{visibility.label}
|
||||
</option>
|
||||
))
|
||||
}
|
||||
@@ -227,11 +228,11 @@ const truncate = (text: string, length: number) => {
|
||||
id="verificationStatus"
|
||||
class="mt-1 w-full rounded-md border border-zinc-700 bg-zinc-900 px-3 py-2 text-sm text-zinc-200 focus:border-blue-500 focus:ring-blue-500 focus:outline-none"
|
||||
>
|
||||
<option value="">All Statuses</option>
|
||||
<option value="">All</option>
|
||||
{
|
||||
Object.values(VerificationStatus).map((status) => (
|
||||
<option value={status} selected={filters.verificationStatus === status}>
|
||||
{status}
|
||||
verificationStatuses.map((status) => (
|
||||
<option value={status.value} selected={filters.verificationStatus === status.value}>
|
||||
{status.label}
|
||||
</option>
|
||||
))
|
||||
}
|
||||
|
||||
@@ -222,7 +222,9 @@ const where = {
|
||||
verificationStatus: {
|
||||
in: includeScams ? uniq([...filters.verification, 'VERIFICATION_FAILED'] as const) : filters.verification,
|
||||
},
|
||||
serviceVisibility: ServiceVisibility.PUBLIC,
|
||||
serviceVisibility: {
|
||||
in: [ServiceVisibility.PUBLIC, ServiceVisibility.ARCHIVED],
|
||||
},
|
||||
overallScore: { gte: filters['min-score'] },
|
||||
acceptedCurrencies: filters.currencies.length
|
||||
? filters['currency-mode'] === 'and'
|
||||
@@ -372,6 +374,7 @@ const [categories, [services, totalServices], countCommunityOnly, attributes] =
|
||||
imageUrl: true,
|
||||
verificationStatus: true,
|
||||
acceptedCurrencies: true,
|
||||
serviceVisibility: true,
|
||||
attributes: {
|
||||
select: {
|
||||
attribute: {
|
||||
|
||||
@@ -30,7 +30,7 @@ import { formatContactMethod } from '../../constants/contactMethods'
|
||||
import { currencies, getCurrencyInfo } from '../../constants/currencies'
|
||||
import { getEventTypeInfo } from '../../constants/eventTypes'
|
||||
import { getKycLevelInfo, kycLevels } from '../../constants/kycLevels'
|
||||
import { serviceVisibilitiesById } from '../../constants/serviceVisibility'
|
||||
import { getServiceVisibilityInfo } from '../../constants/serviceVisibility'
|
||||
import { getTosHighlightRatingInfo } from '../../constants/tosHighlightRating'
|
||||
import { getUserSentimentInfo } from '../../constants/userSentiment'
|
||||
import { getVerificationStatusInfo, verificationStatusesByValue } from '../../constants/verificationStatus'
|
||||
@@ -240,7 +240,11 @@ const watchingDetails = makeWatchingDetails(dbNotificationPreferences, service?.
|
||||
|
||||
if (!service) return Astro.rewrite('/404')
|
||||
|
||||
if (service.serviceVisibility !== 'PUBLIC' && service.serviceVisibility !== 'UNLISTED') {
|
||||
if (
|
||||
service.serviceVisibility !== 'PUBLIC' &&
|
||||
service.serviceVisibility !== 'UNLISTED' &&
|
||||
service.serviceVisibility !== 'ARCHIVED'
|
||||
) {
|
||||
return Astro.rewrite('/404')
|
||||
}
|
||||
|
||||
@@ -356,6 +360,8 @@ const ogImageTemplateData = {
|
||||
score: service.overallScore,
|
||||
imageUrl: service.imageUrl,
|
||||
} satisfies OgImageAllTemplatesWithProps
|
||||
|
||||
const serviceVisibilityInfo = getServiceVisibilityInfo(service.serviceVisibility)
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
@@ -457,16 +463,17 @@ const ogImageTemplateData = {
|
||||
]}
|
||||
>
|
||||
{
|
||||
service.serviceVisibility === 'UNLISTED' && (
|
||||
<div class={cn('mb-4 rounded-md bg-yellow-900/50 p-2 text-sm text-yellow-400')}>
|
||||
(serviceVisibilityInfo.value === 'UNLISTED' || serviceVisibilityInfo.value === 'ARCHIVED') && (
|
||||
<div class={cn('mb-4 rounded-md bg-yellow-900/50 px-3 py-2 text-sm text-yellow-400')}>
|
||||
<Icon
|
||||
name={serviceVisibilitiesById.UNLISTED.icon}
|
||||
class={cn('me-1.5 inline-block size-4 align-[-0.15em]', serviceVisibilitiesById.UNLISTED.iconClass)}
|
||||
name={serviceVisibilityInfo.icon}
|
||||
class="me-1.5 inline-block size-4 align-[-0.15em] text-yellow-500"
|
||||
/>
|
||||
Unlisted service, only accessible via direct link and won't appear in searches.
|
||||
{serviceVisibilityInfo.longDescription}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
<VerificationWarningBanner service={service} />
|
||||
|
||||
<div class="flex items-center gap-4">
|
||||
@@ -1245,7 +1252,8 @@ const ogImageTemplateData = {
|
||||
<div class="flex flex-col gap-2">
|
||||
{
|
||||
service.verificationStatus !== 'VERIFICATION_SUCCESS' &&
|
||||
service.verificationStatus !== 'VERIFICATION_FAILED' && (
|
||||
service.verificationStatus !== 'VERIFICATION_FAILED' &&
|
||||
service.serviceVisibility !== 'ARCHIVED' && (
|
||||
<form
|
||||
method="POST"
|
||||
action={actions.service.requestVerification}
|
||||
|
||||
@@ -103,6 +103,10 @@
|
||||
drop-shadow(0 0 4px color-mix(in oklab, currentColor 60%, transparent));
|
||||
}
|
||||
|
||||
@utility scrollbar-w-none {
|
||||
scrollbar-width: none;
|
||||
}
|
||||
|
||||
@utility checkbox-force-checked {
|
||||
&:not(:checked) {
|
||||
@apply border-transparent! bg-current/50!;
|
||||
|
||||
Reference in New Issue
Block a user