dev 8 months ago
parent 119b327ae4
commit 5e40546c1a

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

@ -41,9 +41,7 @@
{/key}
</div>
<div class="left-0">
<!-- <PnDebug enabled={true} /> -->
</div>

@ -2,6 +2,7 @@
import { appState } from "../data/AppState.svelte";
import type { OptionReference } from "../data/DataConfigTypes";
import {dataConfig} from "../data/DataConfig";
import {formatPrice} from "../utils/formats";
const imgPath : string = dataConfig.sources.imgValues
@ -38,18 +39,36 @@
}
// Formatear precio
function formatearPrecio(cantidad: number): string {
return new Intl.NumberFormat('es-ES', {
style: 'currency',
currency: 'EUR',
minimumFractionDigits: 0,
maximumFractionDigits: 0
}).format(cantidad);
}
// Obtener el precio desde optionRef.amount
const hasPrice = $derived(
optionRef.amount !== undefined &&
optionRef.amount !== 'consultar' &&
typeof optionRef.amount === 'number' &&
optionRef.amount > 0
);
</script>
<button
class="relative border-2 rounded-lg p-3 text-left transition-all hover:shadow-md"
class="relative border-2 rounded-lg p-3 text-left transition-all hover:shadow-md flex flex-col items-center"
class:border-green-600={isSelected}
class:ring-offset-1={isSelected}
class:ring-green-600={isSelected}
class:border-yellow-300={!isSelected && consultation.message}
class:bg-yellow-50={!isSelected && consultation.message}
class:border-gray-200={!isSelected && !consultation.message}
class:border-gray-200={!isSelected}
class:cursor-not-allowed={isDisabled}
onclick={handleClick}
@ -72,9 +91,10 @@
<!-- Imagen -->
{#if optionValue?.thumb}
<img
class="h-20 object-cover mb-2"
src={imgOptSrc}
alt={optionValue.name}
class="w-full h-20 object-cover rounded mb-2"
/>
{:else}
<!--
@ -85,7 +105,7 @@
{/if}
<!-- Nombre -->
<div class="font-medium text-xs mb-1 text-center">
<div class="font-medium text-xm mb-1 text-center">
{optionValue?.name || optionRef.id}
</div>
@ -109,6 +129,17 @@
</div>
{/if}
<!-- Precio -->
{#if hasPrice}
<div class="text-center mt-1">
<span class="w-full inline-block bg-gray-200 px-2 py-1 text-gray-800 text-xm font-semibold rounded">
+ {formatPrice(optionRef.amount as number)}
</span>
</div>
{/if}
<!-- Badge consultar -->
<!--
{#if consultation.required}

@ -29,7 +29,7 @@
<div class="mb-6">
<h4 class="text-sm font-semibold text-gray-800 mb-3">{group.name || 'Opciones' }</h4>
<p class="text-sm mb-2">{group.text}</p>
<div class="grid grid-cols-2 gap-4">
{#each options as option (option.id) }
@ -47,24 +47,8 @@
<!-- ✅ Mensaje de consulta si la opción seleccionada lo requiere -->
{#if selectedConsultation?.required}
<div class="mt-4 bg-orange-50 border-l-4 border-orange-400 rounded-r-lg p-4 shadow-sm">
<div class="flex items-start gap-3">
<div class="flex-shrink-0">
<svg class="w-6 h-6 text-orange-500" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clip-rule="evenodd"/>
</svg>
</div>
<div class="flex-1">
<h5 class="font-semibold text-orange-800 mb-1">
Esta opción requiere consulta
</h5>
{#if selectedConsultation.message}
<p class="text-sm text-orange-700 leading-relaxed">
{selectedConsultation.message}
</p>
{/if}
</div>
</div>
<div class="col-span-2 p-3 bg-yellow-50 border-l-4 border-yellow-400 text-xs text-yellow-800 rounded">
⚠️ {selectedConsultation.message}
</div>
{/if}

@ -255,7 +255,7 @@ class DataConfigStore {
const option = group?.values.find(v => v.id === optionId);
return {
required: option?.amount === 'consultar',
required: !!option?.warn || option?.amount === 'consultar',
message: option?.warn
};
}

@ -37,8 +37,8 @@ export const dataConfig : DataConfig = {
texts: {
error_loading_image : 'Error cargando imagen',
title_options_general: 'Acabados generales',
text_options_general : 'Seleccione las opciones generales para la vivienda',
title_options_general: 'PAVIMENTO GENERAL DE LA VIVIENDA',
text_options_general : 'El pavimento de la vivienda es el mismo en todas las estancias, por lo que la opción elegida será la que se instale también en el resto de la vivienda.',
title_options_view : 'Acabados de la estancia',
title_select_view : 'Seleccione la estancia',
text_options_view : 'Seleccione las opciones de la estancia',
@ -113,14 +113,14 @@ export const dataConfig : DataConfig = {
light: {
value : 'light',
name : 'Light Brush',
name : 'Ground Light',
text : '',
image : 'alicatados/light.jpg',
thumb : 'light_brush_thumb.png',
},
grey: {
value : 'grey',
name : 'Grey Brush',
name : 'Ground Grey',
text : '',
image : 'alicatados/grey.jpg',
thumb : 'grey_brush_thumb.png',
@ -192,7 +192,7 @@ export const dataConfig : DataConfig = {
},
sensow: {
value : 'sensow',
name : 'Senso Watch',
name : 'D-Neo Senso Wash',
text : '',
image : '',
thumb : 'sensow_thumb.jpg',
@ -234,7 +234,7 @@ export const dataConfig : DataConfig = {
// Disposicion cocina
abierta : {
value : 'abierta',
name : 'Cocina integrada',
name : 'Cocina integrada con el salón',
text : '',
image : undefined,
thumb : undefined,
@ -284,7 +284,7 @@ export const dataConfig : DataConfig = {
// Grupo de opciones
suelo: {
id: 'suelo',
name: 'Pavimento',
name: '',
text: '',
help: '',
default: 'trentino',
@ -351,7 +351,11 @@ export const dataConfig : DataConfig = {
default: 'dneo',
values : [
{ id: 'dneo' },
{ id: 'sensow'},
{
id: 'sensow',
amount: 2660,
warn: 'Este inodoro es suspendido'
},
],
},
],
@ -376,7 +380,7 @@ export const dataConfig : DataConfig = {
},
{
id: 'ducha',
amount: 'consultar',
amount: 1186.29,
},
],
},
@ -478,7 +482,8 @@ export const dataConfig : DataConfig = {
{ id: 'mbmb'},
{
id: 'mbpe',
amount: 'consultar',
amount: 'CON COSTE',
warn: 'Coste según tipología y personalización, se contratará con Studio56',
}
],
},
@ -499,7 +504,8 @@ export const dataConfig : DataConfig = {
},
{
id: 'enpe',
amount: 'consultar',
amount: 'CON COSTE',
warn: 'Coste según tipología y personalización, se contratará con Studio56',
}
],
},

@ -0,0 +1,16 @@
// formats.ts
export const formatPrice = (precio?: number): string => {
if (precio === undefined) return '';
return new Intl.NumberFormat('es-ES', {
style: 'currency',
currency: 'EUR',
minimumFractionDigits: 2,
maximumFractionDigits: 2,
useGrouping: true
}).format(precio);
};

@ -94,8 +94,8 @@
<BtViewAccordion
title={dataConfig.texts.title_options_general || 'Acabados Generales'}
desc={dataConfig.texts.text_options_general || 'Seleccione los acabados generales'}
title={dataConfig.texts.title_options_general || 'PAVIMENTO GENERAL DE LA VIVIENDA'}
desc={dataConfig.texts.text_options_general || 'El pavimento de la vivienda es el mismo en todas las estancias, por lo que la opción elegida será la que se instale también en el resto de la vivienda.'}
>
{#each Object.values(dataConfig.options.general) as group (group.id)}
<div class="mb-8 last:mb-0">

Loading…
Cancel
Save

Powered by TurnKey Linux.