Compare commits

..

No commits in common. "1cc14d0a0b58399b7024f09b1926a8d589375308" and "e96bf8dc749b6eb69397a95d12898a094d8b8a1c" have entirely different histories.

9 changed files with 41 additions and 117 deletions

View file

@ -1,17 +0,0 @@
<script lang="ts">
// Parent has to be position relative
import { LoaderCircle } from 'lucide-svelte';
export let loading = false;
</script>
{#if loading}
<div class="absolute inset-0 flex items-center justify-center">
<LoaderCircle class="h-4 w-4 animate-spin" />
</div>
<div class="invisible">
<slot />
</div>
{:else}
<slot />
{/if}

View file

@ -1,25 +1,17 @@
<script lang="ts"> <script lang="ts">
import { Input } from '$lib/components/ui/input'; import { Input } from '$lib/components/ui/input';
import { Button } from '$lib/components/ui/button'; import { Button } from '$lib/components/ui/button';
import { afterNavigate, beforeNavigate, goto } from '$app/navigation'; import { goto } from '$app/navigation';
import { page } from '$app/stores'; import { page } from '$app/stores';
let search = $page.params.query ?? ''; let search = $page.params.query ?? '';
let loading = false;
beforeNavigate(() => {
loading = true;
});
afterNavigate(() => {
loading = false;
});
function handleSubmit() { function handleSubmit() {
goto(`/search/${encodeURIComponent(search)}`); goto(`/search/${encodeURIComponent(search)}`);
} }
</script> </script>
<form class="flex gap-2" on:submit|preventDefault={handleSubmit}> <form class="flex gap-2" on:submit|preventDefault={handleSubmit}>
<Input placeholder="Buscar productos" bind:value={search} disabled={loading} /> <Input placeholder="Buscar productos" bind:value={search} />
<Button type="submit" {loading}>Buscar</Button> <Button type="submit">Buscar</Button>
</form> </form>

View file

@ -2,7 +2,6 @@
import { Button as ButtonPrimitive } from 'bits-ui'; import { Button as ButtonPrimitive } from 'bits-ui';
import { type Events, type Props, buttonVariants } from './index.js'; import { type Events, type Props, buttonVariants } from './index.js';
import { cn } from '$lib/utils.js'; import { cn } from '$lib/utils.js';
import Loading from '$lib/components/Loading.svelte';
type $$Props = Props; type $$Props = Props;
type $$Events = Events; type $$Events = Events;
@ -11,19 +10,16 @@
export let variant: $$Props['variant'] = 'default'; export let variant: $$Props['variant'] = 'default';
export let size: $$Props['size'] = 'default'; export let size: $$Props['size'] = 'default';
export let builders: $$Props['builders'] = []; export let builders: $$Props['builders'] = [];
export let loading = false;
export { className as class }; export { className as class };
</script> </script>
<ButtonPrimitive.Root <ButtonPrimitive.Root
{builders} {builders}
class={cn(buttonVariants({ variant, size, className }), 'relative')} class={cn(buttonVariants({ variant, size, className }))}
type="button" type="button"
{...$$restProps} {...$$restProps}
on:click on:click
on:keydown on:keydown
> >
<Loading {loading}>
<slot /> <slot />
</Loading>
</ButtonPrimitive.Root> </ButtonPrimitive.Root>

View file

@ -32,7 +32,6 @@ type Size = VariantProps<typeof buttonVariants>['size'];
type Props = ButtonPrimitive.Props & { type Props = ButtonPrimitive.Props & {
variant?: Variant; variant?: Variant;
size?: Size; size?: Size;
loading?: boolean;
}; };
type Events = ButtonPrimitive.Events; type Events = ButtonPrimitive.Events;

View file

@ -28,14 +28,3 @@ export const pesosFormatter = new Intl.NumberFormat('es-AR', {
style: 'currency', style: 'currency',
currency: 'ARS' currency: 'ARS'
}); });
export function parseMarcas(marcas: readonly string[]) {
const x = marcas
.map((m) => m.trim().replaceAll(/['`´]/g, ''))
.filter((m) => !['sin marca', 'VARIOS'].includes(m))
.filter((m) => m.length > 0);
if (x.length === 0) {
return ['n/a'];
}
return Array.from(new Set(x));
}

View file

@ -3,13 +3,10 @@
import { ArrowLeft } from 'lucide-svelte'; import { ArrowLeft } from 'lucide-svelte';
import Map from '$lib/components/Map.svelte'; import Map from '$lib/components/Map.svelte';
import Badge from '$lib/components/ui/badge/badge.svelte'; import Badge from '$lib/components/ui/badge/badge.svelte';
import { goto } from '$app/navigation'; import {} from '$app/navigation';
import { generateGoogleMapsLink, pesosFormatter, processBanderaNombre } from '$lib/sepa-utils'; import { generateGoogleMapsLink, pesosFormatter, processBanderaNombre } from '$lib/sepa-utils';
import { page } from '$app/stores';
export let data: PageData; export let data: PageData;
const query = $page.url.searchParams.get('query');
</script> </script>
<svelte:head> <svelte:head>
@ -18,12 +15,7 @@
<div class="flex min-h-screen flex-col"> <div class="flex min-h-screen flex-col">
<div class="max-w-screen flex items-stretch gap-3 overflow-hidden px-2"> <div class="max-w-screen flex items-stretch gap-3 overflow-hidden px-2">
<button <button on:click={() => window.history.back()}>
on:click={() =>
goto(
`/search/${encodeURIComponent(query ?? data.precios[0].productos_descripcion ?? $page.params.id)}`
)}
>
<ArrowLeft class="size-8 flex-shrink-0" /> <ArrowLeft class="size-8 flex-shrink-0" />
</button> </button>
<div class="flex flex-wrap items-center gap-x-2 overflow-hidden p-1"> <div class="flex flex-wrap items-center gap-x-2 overflow-hidden p-1">

View file

@ -8,8 +8,6 @@
import { MapPin } from 'lucide-svelte'; import { MapPin } from 'lucide-svelte';
import Button from '$lib/components/ui/button/button.svelte'; import Button from '$lib/components/ui/button/button.svelte';
import { es } from 'date-fns/locale'; import { es } from 'date-fns/locale';
import { goto } from '$app/navigation';
import { page } from '$app/stores';
export let data: PageData; export let data: PageData;
@ -25,15 +23,7 @@
<div> <div>
<div class="max-w-screen flex items-stretch gap-3 overflow-hidden px-2"> <div class="max-w-screen flex items-stretch gap-3 overflow-hidden px-2">
<button <button on:click={() => window.history.back()}>
on:click={() => {
if (history.length > 1) {
history.back();
} else {
goto(`/id_producto/${$page.params.id}`);
}
}}
>
<ArrowLeft class="size-8 flex-shrink-0" /> <ArrowLeft class="size-8 flex-shrink-0" />
</button> </button>
<div class="flex flex-wrap items-center gap-x-2 overflow-hidden p-1"> <div class="flex flex-wrap items-center gap-x-2 overflow-hidden p-1">

View file

@ -1,12 +1,24 @@
<script lang="ts"> <script lang="ts">
import SearchBar from '$lib/components/SearchBar.svelte'; import SearchBar from '$lib/components/SearchBar.svelte';
import Badge from '$lib/components/ui/badge/badge.svelte';
import Button from '$lib/components/ui/button/button.svelte'; import Button from '$lib/components/ui/button/button.svelte';
import * as Card from '$lib/components/ui/card/index.js';
import { ArrowLeft } from 'lucide-svelte'; import { ArrowLeft } from 'lucide-svelte';
import type { PageData } from './$types'; import type { PageData } from './$types';
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import ProductCard from './ProductCard.svelte';
export let data: PageData; export let data: PageData;
function parseMarcas(marcas: readonly string[]) {
const x = marcas
.map((m) => m.trim().replaceAll(/['`´]/g, ''))
.filter((m) => !['sin marca', 'VARIOS'].includes(m))
.filter((m) => m.length > 0);
if (x.length === 0) {
return ['n/a'];
}
return Array.from(new Set(x));
}
</script> </script>
<svelte:head> <svelte:head>
@ -27,7 +39,26 @@
</p> </p>
{:else} {:else}
{#each data.collapsedProductos as producto} {#each data.collapsedProductos as producto}
<ProductCard {producto} query={data.query} /> <a href={`/id_producto/${producto.id_producto}`} class="my-2 block">
<Card.Root class="transition-colors duration-200 hover:bg-gray-100">
<Card.Header class="block px-3 py-2 pb-0">
<Badge>{parseMarcas(Array.from(producto.marcas)).join('/')}</Badge>
<Badge variant="outline"
>en
{producto.in_datasets_count} cadena{#if producto.in_datasets_count > 1}s{/if}
</Badge>
<Badge variant="outline">EAN {producto.id_producto}</Badge>
</Card.Header>
<Card.Content class="px-3 py-2">
{#each producto.descriptions as description}
<span>{description}</span>
{#if description !== producto.descriptions[producto.descriptions.length - 1]}
<span class="text-gray-500"></span>{' '}
{/if}
{/each}
</Card.Content>
</Card.Root>
</a>
{/each} {/each}
{/if} {/if}
</div> </div>

View file

@ -1,48 +0,0 @@
<script lang="ts">
import * as Card from '$lib/components/ui/card';
import { Badge } from '$lib/components/ui/badge';
import { parseMarcas } from '$lib/sepa-utils';
import { beforeNavigate } from '$app/navigation';
import Loading from '$lib/components/Loading.svelte';
export let producto: {
id_producto: string;
marcas: Set<string>;
in_datasets_count: number;
descriptions: string[];
};
export let query: string | undefined;
let loading = false;
beforeNavigate((x) => {
if (x.to?.params?.id === producto.id_producto) {
loading = true;
}
});
</script>
<a
href={`/id_producto/${producto.id_producto}?query=${encodeURIComponent(query ?? producto.descriptions[0])}`}
class="my-2 block"
>
<Card.Root class="relative transition-colors duration-200 hover:bg-gray-100">
<Loading {loading}>
<Card.Header class="block px-3 py-2 pb-0">
<Badge>{parseMarcas(Array.from(producto.marcas)).join('/')}</Badge>
<Badge variant="outline"
>en
{producto.in_datasets_count} cadena{#if producto.in_datasets_count > 1}s{/if}
</Badge>
<Badge variant="outline">EAN {producto.id_producto}</Badge>
</Card.Header>
<Card.Content class="px-3 py-2">
{#each producto.descriptions as description}
<span>{description}</span>
{#if description !== producto.descriptions[producto.descriptions.length - 1]}
<span class="text-gray-500"></span>{' '}
{/if}
{/each}
</Card.Content>
</Loading>
</Card.Root>
</a>