Compare commits

...

2 Commits

Author SHA1 Message Date
pluja
f4525e3d32 Release 2025-05-22-SwZ1 2025-05-22 23:07:55 +00:00
pluja
ecc8f67fc4 Release 2025-05-22-XDxe 2025-05-22 22:58:18 +00:00
3 changed files with 95 additions and 33 deletions

View File

@@ -27,7 +27,7 @@ export type ButtonProps<Tag extends 'a' | 'button' | 'label' = 'button'> = Props
const button = tv({
slots: {
base: 'inline-flex items-center justify-center gap-2 rounded-lg border transition-colors duration-100 focus-visible:ring-2 focus-visible:ring-current focus-visible:ring-offset-2 focus-visible:ring-offset-black focus-visible:outline-hidden',
base: 'inline-flex shrink-0 items-center justify-center gap-2 rounded-lg border transition-colors duration-100 focus-visible:ring-2 focus-visible:ring-current focus-visible:ring-offset-2 focus-visible:ring-offset-black focus-visible:outline-hidden',
icon: 'size-4 shrink-0',
label: 'text-left whitespace-nowrap',
endIcon: 'size-4 shrink-0',
@@ -52,6 +52,11 @@ const button = tv({
label: 'font-bold tracking-wider uppercase',
},
},
iconOnly: {
true: {
base: 'p-0',
},
},
color: {
black: {
base: 'border-night-500 bg-night-800 hover:bg-night-900 hover:text-day-200 focus-visible:bg-night-500 text-white/50 focus-visible:text-white focus-visible:ring-white',
@@ -122,12 +127,28 @@ const button = tv({
shadow: true,
class: 'shadow-blue-500/30',
},
{
iconOnly: true,
size: 'sm',
class: 'w-8',
},
{
iconOnly: true,
size: 'md',
class: 'w-9',
},
{
iconOnly: true,
size: 'lg',
class: 'w-10',
},
],
defaultVariants: {
size: 'md',
color: 'black',
shadow: false,
disabled: false,
iconOnly: false,
},
})
@@ -153,7 +174,7 @@ const {
icon: iconSlot,
label: labelSlot,
endIcon: endIconSlot,
} = button({ size, color, shadow, disabled })
} = button({ size, color, shadow, disabled, iconOnly: !label && !(!!icon && !!endIcon) })
const ActualTag = disabled && Tag === 'a' ? 'span' : Tag
---

View File

@@ -22,7 +22,7 @@ type Props = HTMLAttributes<'div'> & {
sortSeed?: string
filters: ServicesFiltersObject
includeScams: boolean
countIfIncludingCommunity: number | null
countCommunityOnly: number | null
inlineIcons?: boolean
}
@@ -36,7 +36,7 @@ const {
class: className,
filters,
includeScams,
countIfIncludingCommunity,
countCommunityOnly,
inlineIcons,
...divProps
} = Astro.props
@@ -59,37 +59,67 @@ const urlIfIncludingCommunity = urlWithParams(Astro.url, {
verificationStatusesByValue.COMMUNITY_CONTRIBUTED.slug,
]),
})
const extraIfIncludingCommunity = Math.max(0, (countIfIncludingCommunity ?? 0) - (services?.length ?? 0))
---
<div {...divProps} class={cn('flex-1', className)}>
<div class="flex items-center justify-between">
<span class="text-day-500 text-sm">
<span class="text-day-500 xs:gap-x-3 flex flex-wrap items-center gap-x-2 gap-y-1 text-sm sm:gap-x-6">
{total.toLocaleString()}
{pluralize('result', total)}
<Icon
name="ri:loader-4-line"
id="search-indicator"
class="htmx-request:opacity-100 xs:-mx-1.5 -mx-1 inline-block size-4 animate-spin text-white opacity-0 transition-opacity duration-500 sm:-mx-3"
is:inline={inlineIcons}
/>
{
extraIfIncludingCommunity > 0 && (
<Button
as="a"
href={urlIfIncludingCommunity}
label={`Include +${extraIfIncludingCommunity.toLocaleString()} community contributed`}
size="sm"
class="ml-6 align-[-0.15em]"
icon="ri:search-line"
inlineIcon={inlineIcons}
/>
countCommunityOnly && (
<>
<Button
as="a"
href={urlIfIncludingCommunity}
label={`Include +${countCommunityOnly.toLocaleString()} community contributed`}
size="sm"
class="hidden lg:inline-flex"
icon="ri:search-line"
inlineIcon={inlineIcons}
/>
<Button
as="a"
href={urlIfIncludingCommunity}
label={`Include +${countCommunityOnly.toLocaleString()}`}
size="sm"
class="hidden sm:inline-flex lg:hidden"
icon="ri:search-line"
endIcon="ri:question-line"
classNames={{
endIcon: 'text-yellow-200/50',
}}
inlineIcon={inlineIcons}
/>
<a
href={urlIfIncludingCommunity}
class="border-night-500 bg-night-800 flex items-center gap-1 rounded-md border px-2 py-0.5 text-sm sm:hidden"
>
<Icon
name="ri:search-line"
class="mr-0.5 inline-block size-3.5 shrink-0 align-[-0.15em]"
is:inline={inlineIcons}
/>
Include
{countCommunityOnly.toLocaleString()}
<Icon
name="ri:question-line"
class="inline-block size-3.5 shrink-0 align-[-0.15em] text-yellow-200/50"
is:inline={inlineIcons}
/>
</a>
</>
)
}
<span
id="search-indicator"
class="htmx-request:opacity-100 text-white opacity-0 transition-opacity duration-500"
>
<Icon name="ri:loader-4-line" class="inline-block size-4 animate-spin" is:inline={inlineIcons} />
Loading...
</span>
</span>
<Button
as="a"
@@ -97,6 +127,10 @@ const extraIfIncludingCommunity = Math.max(0, (countIfIncludingCommunity ?? 0) -
label="Add service"
icon="ri:add-line"
inlineIcon={inlineIcons}
class="max-xs:w-9 max-xs:px-0"
classNames={{
label: 'max-xs:hidden',
}}
/>
</div>
@@ -162,11 +196,11 @@ const extraIfIncludingCommunity = Math.max(0, (countIfIncludingCommunity ?? 0) -
inlineIcon={inlineIcons}
/>
)}
{extraIfIncludingCommunity > 0 && (
{countCommunityOnly && (
<Button
as="a"
href={urlIfIncludingCommunity}
label={`Show ${extraIfIncludingCommunity.toLocaleString()} community contributed`}
label={`Show ${countCommunityOnly.toLocaleString()} community contributed`}
icon="ri:search-line"
inlineIcon={inlineIcons}
/>
@@ -207,4 +241,14 @@ const extraIfIncludingCommunity = Math.max(0, (countIfIncludingCommunity ?? 0) -
</>
)
}
<div class="mt-4 text-center">
<Button
as="a"
href="/service-suggestion/new"
label="Add service"
icon="ri:add-line"
inlineIcon={inlineIcons}
class="mx-auto"
/>
</div>
</div>

View File

@@ -310,7 +310,7 @@ const where = {
],
} as const satisfies Prisma.ServiceWhereInput
const [categories, [services, totalServices], countIfIncludingCommunity, attributes] =
const [categories, [services, totalServices], countCommunityOnly, attributes] =
await Astro.locals.banners.tryMany([
[
'Unable to load category filters.',
@@ -416,10 +416,7 @@ const [categories, [services, totalServices], countIfIncludingCommunity, attribu
? prisma.service.count({
where: {
...where,
verificationStatus: {
...where.verificationStatus,
in: uniq([...where.verificationStatus.in, 'COMMUNITY_CONTRIBUTED'] as const),
},
verificationStatus: 'COMMUNITY_CONTRIBUTED',
},
})
: null,
@@ -707,7 +704,7 @@ const showFiltersId = 'show-filters'
sortSeed={filters['sort-seed']}
filters={filters}
includeScams={includeScams}
countIfIncludingCommunity={countIfIncludingCommunity}
countCommunityOnly={countCommunityOnly}
inlineIcons
/>
</div>