mirror of
https://github.com/catdevnull/preciazo.git
synced 2024-11-26 03:26:19 +00:00
Compare commits
No commits in common. "1cc14d0a0b58399b7024f09b1926a8d589375308" and "e96bf8dc749b6eb69397a95d12898a094d8b8a1c" have entirely different histories.
1cc14d0a0b
...
e96bf8dc74
9 changed files with 41 additions and 117 deletions
|
@ -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}
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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));
|
|
||||||
}
|
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
|
Loading…
Reference in a new issue