feat: improved UI
This commit is contained in:
@@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* Tema "shoppy" para la tienda (web app). DaisyUI se carga aquí como CSS ya
|
||||||
|
* compilado desde CDN, no como plugin de Tailwind, así que un tema nuevo se
|
||||||
|
* declara con CSS plano de toda la vida: variables bajo [data-theme="..."],
|
||||||
|
* exactamente igual que los temas que trae DaisyUI de fábrica.
|
||||||
|
*/
|
||||||
|
|
||||||
|
[data-theme='shoppy'] {
|
||||||
|
color-scheme: light;
|
||||||
|
|
||||||
|
--color-base-100: #fbf8f3;
|
||||||
|
--color-base-200: #f1ece2;
|
||||||
|
--color-base-300: #e3dbc9;
|
||||||
|
--color-base-content: #241f2e;
|
||||||
|
|
||||||
|
--color-primary: #4f46e5;
|
||||||
|
--color-primary-content: #ffffff;
|
||||||
|
--color-secondary: #d97706;
|
||||||
|
--color-secondary-content: #ffffff;
|
||||||
|
--color-accent: #0d9488;
|
||||||
|
--color-accent-content: #ffffff;
|
||||||
|
--color-neutral: #241f2e;
|
||||||
|
--color-neutral-content: #f1ece2;
|
||||||
|
|
||||||
|
--color-info: #0ea5e9;
|
||||||
|
--color-info-content: #ffffff;
|
||||||
|
--color-success: #16a34a;
|
||||||
|
--color-success-content: #ffffff;
|
||||||
|
--color-warning: #f59e0b;
|
||||||
|
--color-warning-content: #241f2e;
|
||||||
|
--color-error: #dc2626;
|
||||||
|
--color-error-content: #ffffff;
|
||||||
|
|
||||||
|
--radius-box: 1rem;
|
||||||
|
--radius-field: 0.65rem;
|
||||||
|
--radius-selector: 0.65rem;
|
||||||
|
--size-field: 0.25rem;
|
||||||
|
--size-selector: 0.25rem;
|
||||||
|
--border: 1px;
|
||||||
|
--depth: 1;
|
||||||
|
--noise: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme='shoppy-dark'] {
|
||||||
|
color-scheme: dark;
|
||||||
|
|
||||||
|
--color-base-100: #17151f;
|
||||||
|
--color-base-200: #1e1b28;
|
||||||
|
--color-base-300: #2b2736;
|
||||||
|
--color-base-content: #e9e5da;
|
||||||
|
|
||||||
|
--color-primary: #818cf8;
|
||||||
|
--color-primary-content: #1a1550;
|
||||||
|
--color-secondary: #fbbf6d;
|
||||||
|
--color-secondary-content: #331f00;
|
||||||
|
--color-accent: #2dd4bf;
|
||||||
|
--color-accent-content: #002620;
|
||||||
|
--color-neutral: #e9e5da;
|
||||||
|
--color-neutral-content: #17151f;
|
||||||
|
|
||||||
|
--color-info: #38bdf8;
|
||||||
|
--color-info-content: #002233;
|
||||||
|
--color-success: #4ade80;
|
||||||
|
--color-success-content: #002b0c;
|
||||||
|
--color-warning: #fbbf24;
|
||||||
|
--color-warning-content: #2b1900;
|
||||||
|
--color-error: #f87171;
|
||||||
|
--color-error-content: #2b0000;
|
||||||
|
|
||||||
|
--radius-box: 1rem;
|
||||||
|
--radius-field: 0.65rem;
|
||||||
|
--radius-selector: 0.65rem;
|
||||||
|
--size-field: 0.25rem;
|
||||||
|
--size-selector: 0.25rem;
|
||||||
|
--border: 1px;
|
||||||
|
--depth: 1;
|
||||||
|
--noise: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Detalles que no dependen de Tailwind/DaisyUI */
|
||||||
|
::selection {
|
||||||
|
background-color: var(--color-primary);
|
||||||
|
color: var(--color-primary-content);
|
||||||
|
}
|
||||||
|
|
||||||
|
:focus-visible {
|
||||||
|
outline: 2px solid var(--color-primary);
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
}
|
||||||
@@ -4,14 +4,14 @@ const darkIcon = document.getElementById('theme-toggle-dark-icon')
|
|||||||
const lightIcon = document.getElementById('theme-toggle-light-icon')
|
const lightIcon = document.getElementById('theme-toggle-light-icon')
|
||||||
|
|
||||||
if (currentTheme === 'dark') {
|
if (currentTheme === 'dark') {
|
||||||
document.documentElement.setAttribute('data-theme', 'forest')
|
document.documentElement.setAttribute('data-theme', 'shoppy-dark')
|
||||||
|
|
||||||
if (darkIcon !== null && lightIcon !== null) {
|
if (darkIcon !== null && lightIcon !== null) {
|
||||||
darkIcon.classList.add('hidden')
|
darkIcon.classList.add('hidden')
|
||||||
lightIcon.classList.remove('hidden')
|
lightIcon.classList.remove('hidden')
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
document.documentElement.setAttribute('data-theme', 'cupcake')
|
document.documentElement.setAttribute('data-theme', 'shoppy')
|
||||||
|
|
||||||
if (darkIcon !== null && lightIcon !== null) {
|
if (darkIcon !== null && lightIcon !== null) {
|
||||||
darkIcon.classList.remove('hidden')
|
darkIcon.classList.remove('hidden')
|
||||||
@@ -24,12 +24,12 @@ function switchTheme() {
|
|||||||
const theme = localStorage.getItem('theme')
|
const theme = localStorage.getItem('theme')
|
||||||
|
|
||||||
if (theme === 'dark') {
|
if (theme === 'dark') {
|
||||||
document.documentElement.setAttribute('data-theme', 'cupcake')
|
document.documentElement.setAttribute('data-theme', 'shoppy')
|
||||||
localStorage.setItem('theme', 'light')
|
localStorage.setItem('theme', 'light')
|
||||||
darkIcon.classList.remove('hidden')
|
darkIcon.classList.remove('hidden')
|
||||||
lightIcon.classList.add('hidden')
|
lightIcon.classList.add('hidden')
|
||||||
} else {
|
} else {
|
||||||
document.documentElement.setAttribute('data-theme', 'forest')
|
document.documentElement.setAttribute('data-theme', 'shoppy-dark')
|
||||||
localStorage.setItem('theme', 'dark')
|
localStorage.setItem('theme', 'dark')
|
||||||
lightIcon.classList.remove('hidden')
|
lightIcon.classList.remove('hidden')
|
||||||
darkIcon.classList.add('hidden')
|
darkIcon.classList.add('hidden')
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
<input type="hidden" name="product" value="{{ product.pk }}">
|
<input type="hidden" name="product" value="{{ product.pk }}">
|
||||||
|
|
||||||
{% if product.has_variants %}
|
{% if product.has_variants %}
|
||||||
<div class="mb-4">
|
<div class="mb-3">
|
||||||
<label for="variant">{% translate 'Variante' %}</label>
|
<label for="variant" class="sr-only">{% translate 'Variante' %}</label>
|
||||||
<select class="input" id="variant" name="variant">
|
<select class="select select-bordered {% if size == 'sm' %}select-sm{% endif %} w-full" id="variant" name="variant">
|
||||||
{% for variant in product.variants.all %}
|
{% for variant in product.variants.all %}
|
||||||
<option value="{{ variant.pk }}" {% if not variant.stock %}disabled{% endif %}>
|
<option value="{{ variant.pk }}" {% if not variant.stock %}disabled{% endif %}>
|
||||||
{% for attribute_value in variant.attribute_values.all %}{{ attribute_value }}{% if not forloop.last %}, {% endif %}{% endfor %}
|
{% for attribute_value in variant.attribute_values.all %}{{ attribute_value }}{% if not forloop.last %}, {% endif %}{% endfor %}
|
||||||
@@ -17,12 +17,11 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<div class="flex items-center">
|
<div class="flex items-center gap-2">
|
||||||
<input class="input mr-4" id="quantity" aria-label="quantity" type="number" min="1" max="10" name="quantity" value="1">
|
<input class="input input-bordered {% if size == 'sm' %}input-sm w-16{% else %}w-20{% endif %} text-center" id="quantity" aria-label="{% translate 'Cantidad' %}" type="number" min="1" max="10" name="quantity" value="1">
|
||||||
<button class="btn btn-primary">
|
<button class="btn btn-primary {% if size == 'sm' %}btn-sm{% endif %} flex-1">
|
||||||
{% include 'components/icons/add_cart.svg' %}
|
{% include 'components/icons/add_cart.svg' %}
|
||||||
{% translate 'Añadir al carrito' %}
|
{% if size == 'sm' %}{% translate 'Añadir' %}{% else %}{% translate 'Añadir al carrito' %}{% endif %}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -1,94 +1,79 @@
|
|||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
<section class=" py-2 antialiased md:py-8">
|
<section class="py-6 md:py-12 antialiased">
|
||||||
<form action="{% url 'web:cart_detail' %}" method="post">
|
<form action="{% url 'web:cart_detail' %}" method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<div class="mx-auto max-w-screen-xl px-4 2xl:px-0">
|
<div class="max-w-screen-xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<h2 class="text-xl font-semibold sm:text-2xl">{% translate 'Carrito' %}</h2>
|
<h2 class="text-xl sm:text-2xl font-display font-bold mb-6">{% translate 'Carrito' %}</h2>
|
||||||
|
|
||||||
<div class="mt-4 sm:mt-6 md:gap-6 lg:flex lg:items-start xl:gap-8">
|
<div class="lg:grid lg:grid-cols-3 lg:gap-8 xl:gap-12">
|
||||||
<div class="mx-auto w-full flex-none lg:max-w-2xl xl:max-w-4xl">
|
<div class="lg:col-span-2">
|
||||||
<div class="space-y-6">
|
<div class="flex flex-col gap-4">
|
||||||
|
|
||||||
{% for item in items %}
|
{% for item in items %}
|
||||||
<div class="rounded-lg p-4 shadow-md md:p-6">
|
<div class="rounded-2xl border border-base-300 bg-base-100 p-4 md:p-6">
|
||||||
<div class="space-y-4 flex items-center justify-between gap-6 space-y-0">
|
<div class="flex items-center gap-4">
|
||||||
<a href="{% url 'web:product_detail' pk=item.product.pk slug=item.product.slug %}"
|
<a href="{% url 'web:product_detail' pk=item.product.pk slug=item.product.slug %}" class="shrink-0">
|
||||||
class="shrink-0 md:order-1">
|
<img class="h-20 w-20 rounded-lg object-contain bg-base-200/50 p-1" src="{{ item.product.images.all.0.s.url }}"
|
||||||
<img class="h-20 w-20" src="{{ item.product.images.all.0.s.url }}"
|
|
||||||
alt="{{ item.product.name }}"/>
|
|
||||||
<img class="hidden h-20 w-20" src="{{ item.product.images.all.0.s_dark.url }}"
|
|
||||||
alt="{{ item.product.name }}"/>
|
alt="{{ item.product.name }}"/>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<div class="w-full min-w-0 flex-1 space-y-4 md:order-2 md:max-w-md">
|
<div class="w-full min-w-0 flex-1">
|
||||||
<a href="{% url 'web:product_detail' pk=item.product.pk slug=item.product.slug %}"
|
<a href="{% url 'web:product_detail' pk=item.product.pk slug=item.product.slug %}"
|
||||||
class="text-base font-medium hover:underline "
|
class="text-base font-medium hover:text-primary"
|
||||||
>
|
>
|
||||||
{{ item.product.name }}
|
{{ item.product.name }}
|
||||||
</a>
|
</a>
|
||||||
{% if item.variant %}
|
{% if item.variant %}
|
||||||
<p class="text-sm">
|
<p class="text-sm text-base-content/60">
|
||||||
{% for attribute_value in item.variant.attribute_values.all %}{{ attribute_value }}{% if not forloop.last %}, {% endif %}{% endfor %}
|
{% for attribute_value in item.variant.attribute_values.all %}{{ attribute_value }}{% if not forloop.last %}, {% endif %}{% endfor %}
|
||||||
</p>
|
</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<div class="flex items-center gap-4">
|
<form hx-post="{% url 'web:delete_cart_item' pk=item.pk %}" hx-swap="none" class="mt-2">
|
||||||
<form class="flex" hx-post="{% url 'web:delete_cart_item' pk=item.pk %}"
|
|
||||||
hx-swap="none">
|
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
class="inline-flex items-center text-sm font-medium text-red-700 hover:underline cursor-pointer"
|
class="inline-flex items-center gap-1 text-sm font-medium text-error hover:underline cursor-pointer"
|
||||||
>
|
>
|
||||||
{% include 'components/icons/x.svg' %}
|
{% include 'components/icons/x.svg' %}
|
||||||
{% translate 'Quitar' %}
|
{% translate 'Quitar' %}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<label for="counter-input" class="sr-only">{% translate 'Cantidad' %}</label>
|
<div class="text-end shrink-0">
|
||||||
<div class="flex items-center justify-between md:order-3 md:justify-end">
|
<span class="block text-sm text-base-content/60 mb-1">{{ item.quantity }}x</span>
|
||||||
<div class="flex items-center">
|
<p class="text-base font-bold">
|
||||||
<span class="w-10 shrink-0 text-center text-sm font-medium focus:outline-none focus:ring-0">
|
|
||||||
{{ item.quantity }}x
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="text-end md:order-4 md:w-32">
|
|
||||||
<p class="text-base font-bold ">
|
|
||||||
{{ item.price.price_with_tax }}€
|
{{ item.price.price_with_tax }}€
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
{% if items.count == 0 %}
|
{% if items.count == 0 %}
|
||||||
<p class="text-base font-normal ">
|
<div class="rounded-2xl border border-base-300 bg-base-100 p-8 text-center">
|
||||||
|
<p class="text-base-content/70 mb-2">
|
||||||
{% translate 'No hay nada en el carrito...' %}
|
{% translate 'No hay nada en el carrito...' %}
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<a href="{% url 'web:index' %}" class="link link-primary">
|
||||||
<a href="{% url 'web:index' %}" title=""
|
|
||||||
class="inline-flex items-center gap-2 text-sm font-medium text-primary-700 underline hover:no-underline ">
|
|
||||||
{% translate 'Volver a inicio' %}
|
{% translate 'Volver a inicio' %}
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<h2 class="text-xl font-semibold sm:text-2xl">
|
<h2 class="text-lg sm:text-xl font-display font-semibold mt-4">
|
||||||
{% translate 'Dirección de envío' %}
|
{% translate 'Dirección de envío' %}
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<section class="p-4 rounded-lg">
|
<section class="rounded-2xl border border-base-300 bg-base-100 p-4 md:p-6">
|
||||||
|
<div class="grid gap-4 sm:grid-cols-2">
|
||||||
<div class="grid gap-4 sm:grid-cols-2 sm:gap-6 my-2">
|
|
||||||
{% if user.is_anonymous %}
|
{% if user.is_anonymous %}
|
||||||
<div class="sm:col-span-2">
|
<div class="sm:col-span-2">
|
||||||
<label for="email"
|
<label for="email" class="block mb-1 text-sm font-medium">
|
||||||
class="block mb-2 text-sm font-medium ">
|
|
||||||
{% translate 'E-Mail' %}</label>
|
{% translate 'E-Mail' %}</label>
|
||||||
<input type="text" name="email" id="email"
|
<input type="text" name="email" id="email"
|
||||||
class="input"
|
class="input input-bordered w-full"
|
||||||
placeholder="{% translate 'E-Mail' %}"
|
placeholder="{% translate 'E-Mail' %}"
|
||||||
value=""
|
value=""
|
||||||
required=""
|
required=""
|
||||||
@@ -98,44 +83,40 @@
|
|||||||
<input type="hidden" name="email" value="{{ user.email }}">
|
<input type="hidden" name="email" value="{{ user.email }}">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="sm:col-span-2">
|
<div class="sm:col-span-2">
|
||||||
<label for="shipping_address_full_name"
|
<label for="shipping_address_full_name" class="block mb-1 text-sm font-medium">
|
||||||
class="block mb-2 text-sm font-medium ">
|
|
||||||
{% translate 'Nombre completo' %}</label>
|
{% translate 'Nombre completo' %}</label>
|
||||||
<input type="text" name="shipping_address_full_name" id="shipping_address_full_name"
|
<input type="text" name="shipping_address_full_name" id="shipping_address_full_name"
|
||||||
class="input"
|
class="input input-bordered w-full mb-3"
|
||||||
placeholder="{% translate 'Nombre completo' %}"
|
placeholder="{% translate 'Nombre completo' %}"
|
||||||
value="{% if shipping_address %}{{ shipping_address.full_name }}{% endif %}"
|
value="{% if shipping_address %}{{ shipping_address.full_name }}{% endif %}"
|
||||||
required=""
|
required=""
|
||||||
>
|
>
|
||||||
<label for="shipping_address"
|
<label for="shipping_address" class="block mb-1 text-sm font-medium">
|
||||||
class="block my-2 text-sm font-medium ">
|
|
||||||
{% translate 'Dirección' %}</label>
|
{% translate 'Dirección' %}</label>
|
||||||
<input type="text" name="shipping_address" id="shipping_address"
|
<input type="text" name="shipping_address" id="shipping_address"
|
||||||
class="input"
|
class="input input-bordered w-full"
|
||||||
placeholder="{% translate 'Dirección' %}"
|
placeholder="{% translate 'Dirección' %}"
|
||||||
value="{% if shipping_address %}{{ shipping_address.address }}{% endif %}"
|
value="{% if shipping_address %}{{ shipping_address.address }}{% endif %}"
|
||||||
required=""
|
required=""
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full">
|
<div>
|
||||||
<label for="shipping_address_town"
|
<label for="shipping_address_town" class="block mb-1 text-sm font-medium">
|
||||||
class="block mb-2 text-sm font-medium ">
|
|
||||||
{% translate 'Localidad' %}
|
{% translate 'Localidad' %}
|
||||||
</label>
|
</label>
|
||||||
<input type="text" name="shipping_address_town" id="shipping_address_town"
|
<input type="text" name="shipping_address_town" id="shipping_address_town"
|
||||||
class="input"
|
class="input input-bordered w-full"
|
||||||
placeholder="{% translate 'Localidad' %}"
|
placeholder="{% translate 'Localidad' %}"
|
||||||
value="{% if shipping_address %}{{ shipping_address.address_town }}{% endif %}"
|
value="{% if shipping_address %}{{ shipping_address.address_town }}{% endif %}"
|
||||||
required=""
|
required=""
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full">
|
<div>
|
||||||
<label for="shipping_address_zip"
|
<label for="shipping_address_zip" class="block mb-1 text-sm font-medium">
|
||||||
class="block mb-2 text-sm font-medium ">
|
|
||||||
{% translate 'Código postal' %}
|
{% translate 'Código postal' %}
|
||||||
</label>
|
</label>
|
||||||
<input type="text" name="shipping_address_zip" id="shipping_address_zip"
|
<input type="text" name="shipping_address_zip" id="shipping_address_zip"
|
||||||
class="input"
|
class="input input-bordered w-full"
|
||||||
placeholder="{% translate 'Código postal' %}"
|
placeholder="{% translate 'Código postal' %}"
|
||||||
value="{% if shipping_address %}{{ shipping_address.address_zip }}{% endif %}"
|
value="{% if shipping_address %}{{ shipping_address.address_zip }}{% endif %}"
|
||||||
required=""
|
required=""
|
||||||
@@ -143,80 +124,72 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label for="shipping_address_state"
|
<label for="shipping_address_state" class="block mb-1 text-sm font-medium">
|
||||||
class="block mb-2 text-sm font-medium ">
|
|
||||||
{% translate 'Provincia' %}
|
{% translate 'Provincia' %}
|
||||||
</label>
|
</label>
|
||||||
<input type="text" name="shipping_address_state" id="shipping_address_state"
|
<input type="text" name="shipping_address_state" id="shipping_address_state"
|
||||||
class="input"
|
class="input input-bordered w-full"
|
||||||
placeholder="{% translate 'Provincia' %}"
|
placeholder="{% translate 'Provincia' %}"
|
||||||
value="{% if shipping_address %}{{ shipping_address.address_state }}{% endif %}"
|
value="{% if shipping_address %}{{ shipping_address.address_state }}{% endif %}"
|
||||||
required=""
|
required=""
|
||||||
>
|
>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="shipping_address_country" class="block mb-2 text-sm font-medium ">
|
<label for="shipping_address_country" class="block mb-1 text-sm font-medium">
|
||||||
{% translate 'País' %}
|
{% translate 'País' %}
|
||||||
</label>
|
</label>
|
||||||
<input type="text" name="shipping_address_country" id="shipping_address_country"
|
<input type="text" name="shipping_address_country" id="shipping_address_country"
|
||||||
class="input"
|
class="input input-bordered w-full"
|
||||||
placeholder="{% translate 'País' %}"
|
placeholder="{% translate 'País' %}"
|
||||||
value="{% if shipping_address %}{{ shipping_address.address_country }}{% endif %}"
|
value="{% if shipping_address %}{{ shipping_address.address_country }}{% endif %}"
|
||||||
required=""
|
required=""
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<h2 class="text-xl font-semibold sm:text-2xl">
|
<h2 class="text-lg sm:text-xl font-display font-semibold mt-4">
|
||||||
{% translate 'Dirección de facturación' %}
|
{% translate 'Dirección de facturación' %}
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<section class="p-4 rounded-lg">
|
<section class="rounded-2xl border border-base-300 bg-base-100 p-4 md:p-6">
|
||||||
|
<div class="grid gap-4 sm:grid-cols-2">
|
||||||
<div class="grid gap-4 sm:grid-cols-2 sm:gap-6 my-2">
|
|
||||||
<div class="sm:col-span-2">
|
<div class="sm:col-span-2">
|
||||||
<label for="billing_address_full_name"
|
<label for="billing_address_full_name" class="block mb-1 text-sm font-medium">
|
||||||
class="block mb-2 text-sm font-medium ">
|
|
||||||
{% translate 'Nombre completo' %}</label>
|
{% translate 'Nombre completo' %}</label>
|
||||||
<input type="text" name="billing_address_full_name" id="billing_address_full_name"
|
<input type="text" name="billing_address_full_name" id="billing_address_full_name"
|
||||||
class="input"
|
class="input input-bordered w-full mb-3"
|
||||||
placeholder="{% translate 'Nombre completo' %}"
|
placeholder="{% translate 'Nombre completo' %}"
|
||||||
value="{% if billing_address %}{{ billing_address.full_name }}{% endif %}"
|
value="{% if billing_address %}{{ billing_address.full_name }}{% endif %}"
|
||||||
required=""
|
required=""
|
||||||
>
|
>
|
||||||
<label for="billing_address"
|
<label for="billing_address" class="block mb-1 text-sm font-medium">
|
||||||
class="block my-2 text-sm font-medium ">
|
|
||||||
{% translate 'Dirección' %}
|
{% translate 'Dirección' %}
|
||||||
</label>
|
</label>
|
||||||
<input type="text" name="billing_address" id="billing_address"
|
<input type="text" name="billing_address" id="billing_address"
|
||||||
class="input"
|
class="input input-bordered w-full"
|
||||||
placeholder="{% translate 'Dirección' %}"
|
placeholder="{% translate 'Dirección' %}"
|
||||||
value="{% if billing_address %}{{ billing_address.address }}{% endif %}"
|
value="{% if billing_address %}{{ billing_address.address }}{% endif %}"
|
||||||
required=""
|
required=""
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full">
|
<div>
|
||||||
<label for="billing_address_town"
|
<label for="billing_address_town" class="block mb-1 text-sm font-medium">
|
||||||
class="block mb-2 text-sm font-medium ">
|
|
||||||
{% translate 'Localidad' %}
|
{% translate 'Localidad' %}
|
||||||
</label>
|
</label>
|
||||||
<input type="text" name="billing_address_town" id="billing_address_town"
|
<input type="text" name="billing_address_town" id="billing_address_town"
|
||||||
class="input"
|
class="input input-bordered w-full"
|
||||||
placeholder="{% translate 'Localidad' %}"
|
placeholder="{% translate 'Localidad' %}"
|
||||||
value="{% if billing_address %}{{ billing_address.address_town }}{% endif %}"
|
value="{% if billing_address %}{{ billing_address.address_town }}{% endif %}"
|
||||||
required=""
|
required=""
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full">
|
<div>
|
||||||
<label for="billing_address_zip"
|
<label for="billing_address_zip" class="block mb-1 text-sm font-medium">
|
||||||
class="block mb-2 text-sm font-medium ">
|
|
||||||
{% translate 'Código postal' %}
|
{% translate 'Código postal' %}
|
||||||
</label>
|
</label>
|
||||||
<input type="text" name="billing_address_zip" id="billing_address_zip"
|
<input type="text" name="billing_address_zip" id="billing_address_zip"
|
||||||
class="input"
|
class="input input-bordered w-full"
|
||||||
placeholder="{% translate 'Código postal' %}"
|
placeholder="{% translate 'Código postal' %}"
|
||||||
value="{% if billing_address %}{{ billing_address.address_zip }}{% endif %}"
|
value="{% if billing_address %}{{ billing_address.address_zip }}{% endif %}"
|
||||||
required=""
|
required=""
|
||||||
@@ -224,54 +197,44 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label for="billing_address_state"
|
<label for="billing_address_state" class="block mb-1 text-sm font-medium">
|
||||||
class="block mb-2 text-sm font-medium ">
|
|
||||||
{% translate 'Provincia' %}
|
{% translate 'Provincia' %}
|
||||||
</label>
|
</label>
|
||||||
<input type="text" name="billing_address_state" id="billing_address_state"
|
<input type="text" name="billing_address_state" id="billing_address_state"
|
||||||
class="input"
|
class="input input-bordered w-full"
|
||||||
placeholder="{% translate 'Provincia' %}"
|
placeholder="{% translate 'Provincia' %}"
|
||||||
value="{% if billing_address %}{{ billing_address.address_state }}{% endif %}"
|
value="{% if billing_address %}{{ billing_address.address_state }}{% endif %}"
|
||||||
required=""
|
required=""
|
||||||
>
|
>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="billing_address_country"
|
<label for="billing_address_country" class="block mb-1 text-sm font-medium">
|
||||||
class="block mb-2 text-sm font-medium ">
|
|
||||||
{% translate 'País' %}
|
{% translate 'País' %}
|
||||||
</label>
|
</label>
|
||||||
<input type="text" name="billing_address_country" id="billing_address_country"
|
<input type="text" name="billing_address_country" id="billing_address_country"
|
||||||
class="input"
|
class="input input-bordered w-full"
|
||||||
placeholder="{% translate 'País' %}"
|
placeholder="{% translate 'País' %}"
|
||||||
value="{% if billing_address %}{{ billing_address.address_country }}{% endif %}"
|
value="{% if billing_address %}{{ billing_address.address_country }}{% endif %}"
|
||||||
required=""
|
required=""
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<h2 class="text-xl mb-4 font-semibold sm:text-2xl">
|
<h2 class="text-lg sm:text-xl font-display font-semibold mb-3">
|
||||||
{% translate 'Opciones de envío' %}
|
{% translate 'Opciones de envío' %}
|
||||||
</h2>
|
</h2>
|
||||||
<article class="rounded-lg">
|
<article class="rounded-2xl border border-base-300 bg-base-100 divide-y divide-base-300">
|
||||||
|
|
||||||
{% for shipping_method in shipping_methods %}
|
{% for shipping_method in shipping_methods %}
|
||||||
<div class="p-4">
|
<div class="p-4 flex items-center gap-3">
|
||||||
<input type="radio" id="shipping_method_{{ shipping_method.pk }}"
|
<input type="radio" id="shipping_method_{{ shipping_method.pk }}" class="radio radio-primary"
|
||||||
name="shipping_method"
|
name="shipping_method"
|
||||||
value="{{ shipping_method.pk }}" {% if forloop.first %}checked{% endif %}>
|
value="{{ shipping_method.pk }}" {% if forloop.first %}checked{% endif %}>
|
||||||
<label for="shipping_method_{{ shipping_method.pk }}"
|
<label for="shipping_method_{{ shipping_method.pk }}" class="cursor-pointer">
|
||||||
class=" ">
|
{{ shipping_method.name }} — {{ shipping_method.shipping_product.price.price_with_tax }}€
|
||||||
{{ shipping_method.name }} - {{ shipping_method.shipping_product.price.price_with_tax }}€
|
|
||||||
</label>
|
</label>
|
||||||
{% if not forloop.last %}
|
|
||||||
</div>
|
</div>
|
||||||
<hr class="h-px mx-4"/>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</article>
|
</article>
|
||||||
</section>
|
</section>
|
||||||
@@ -279,75 +242,52 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Resumen del pedido -->
|
<!-- Resumen del pedido -->
|
||||||
<div class="mx-auto mt-6 max-w-4xl flex-1 space-y-6 lg:mt-0 lg:w-full">
|
<div class="mt-6 lg:mt-0">
|
||||||
<div
|
<div class="rounded-2xl border border-base-300 bg-base-100 p-4 sm:p-6 sticky top-20">
|
||||||
class="space-y-4 rounded-lg p-4 shadow-md sm:p-6">
|
<p class="text-lg font-display font-semibold mb-4">
|
||||||
<p class="text-xl font-semibold ">
|
|
||||||
{% translate 'Resumen del pedido' %}
|
{% translate 'Resumen del pedido' %}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="space-y-4">
|
<div class="flex flex-col gap-2 text-sm">
|
||||||
<div class="space-y-2">
|
<div class="flex items-center justify-between">
|
||||||
<dl class="flex items-center justify-between gap-4">
|
<span class="text-base-content/70">{% translate 'Base imponible' %}</span>
|
||||||
<dt
|
<span class="font-medium">{{ base_total }} €</span>
|
||||||
class="text-base font-normal ">
|
|
||||||
{% translate 'Base imponible' %}
|
|
||||||
</dt>
|
|
||||||
<dd class="text-base font-medium ">{{ base_total }} €
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dl class="flex items-center justify-between gap-4">
|
|
||||||
<dt class="text-base font-normal ">
|
|
||||||
{% translate 'Descuentos' %}
|
|
||||||
</dt>
|
|
||||||
<dd class="text-base font-medium text-green-600">-{{ savings }} €</dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dl class="flex items-center justify-between gap-4">
|
|
||||||
<dt class="text-base font-normal">
|
|
||||||
{% translate 'Gastos de envío' %}
|
|
||||||
</dt>
|
|
||||||
<dd class="text-base font-medium ">
|
|
||||||
{{ shipping_cost }} €
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dl class="flex items-center justify-between gap-4">
|
|
||||||
<dt class="text-base font-normal ">
|
|
||||||
{% translate 'Impuestos' %}
|
|
||||||
</dt>
|
|
||||||
<dd class="text-base font-medium ">{{ tax_total }} €
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<dl class="flex items-center justify-between gap-4 pt-2 ">
|
<div class="flex items-center justify-between">
|
||||||
<dt class="text-base font-bold ">{% translate 'Total' %}
|
<span class="text-base-content/70">{% translate 'Descuentos' %}</span>
|
||||||
</dt>
|
<span class="font-medium text-success">-{{ savings }} €</span>
|
||||||
<dd class="text-base font-bold ">{{ total }} €</dd>
|
|
||||||
</dl>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex justify-center items-center">
|
<div class="flex items-center justify-between">
|
||||||
<button
|
<span class="text-base-content/70">{% translate 'Gastos de envío' %}</span>
|
||||||
class="btn btn-primary">
|
<span class="font-medium">{{ shipping_cost }} €</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<span class="text-base-content/70">{% translate 'Impuestos' %}</span>
|
||||||
|
<span class="font-medium">{{ tax_total }} €</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex items-center justify-between border-t border-base-300 mt-4 pt-4">
|
||||||
|
<span class="font-display font-bold">{% translate 'Total' %}</span>
|
||||||
|
<span class="font-display font-bold text-xl">{{ total }} €</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button class="btn btn-primary w-full mt-6">
|
||||||
{% translate 'Terminar pedido' %}
|
{% translate 'Terminar pedido' %}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
|
||||||
|
|
||||||
|
<div class="flex items-center justify-center gap-2 mt-3">
|
||||||
<div class="flex items-center justify-center gap-2">
|
<span class="text-sm text-base-content/60">{% translate 'o' %}</span>
|
||||||
<span class="text-sm font-normal "> {% translate 'o' %} </span>
|
<a href="{% url 'web:index' %}" class="link link-primary text-sm">
|
||||||
<a href="{% url 'web:index' %}" title=""
|
|
||||||
class="inline-flex items-center gap-2 text-sm font-medium text-primary-700 underline hover:no-underline ">
|
|
||||||
{% translate 'Seguir comprando' %}
|
{% translate 'Seguir comprando' %}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</section>
|
</section>
|
||||||
@@ -1,75 +1,43 @@
|
|||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
<button
|
{% if cart.items.count == 0 %}
|
||||||
hx-on:click="htmx.toggleClass(htmx.find('#myCartDropdown1'), 'hidden'); htmx.addClass(htmx.find('#userDropdown1'), 'hidden')"
|
<p class="text-sm text-base-content/70 py-2">{% translate 'No hay nada en el carrito' %}</p>
|
||||||
id="myCartDropdownButton1"
|
{% else %}
|
||||||
data-dropdown-toggle="myCartDropdown1" type="button"
|
<ul class="flex flex-col gap-3 max-h-80 overflow-y-auto">
|
||||||
class="icon-button">
|
|
||||||
{% include 'components/icons/cart.svg' %}
|
|
||||||
<span class="hidden sm:flex">
|
|
||||||
{% translate 'Carrito' %}</span>
|
|
||||||
<span class="ml-1">({{ cart.items.count }})</span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<!-- Cart -->
|
|
||||||
<div id="myCartDropdown1"
|
|
||||||
class="cart-navbar-floating hidden"
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
{% if cart.items.count == 0 %}
|
|
||||||
<h2 class="text-sm font-medium ">No hay nada en el carrito</h2>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% for cart_item in cart.items.all %}
|
{% for cart_item in cart.items.all %}
|
||||||
<div>
|
<li class="flex items-start gap-3 {% if not forloop.last %}pb-3 border-b border-base-300{% endif %}">
|
||||||
|
<a href="{% url 'web:product_detail' pk=cart_item.product.pk slug=cart_item.product.slug %}" class="shrink-0">
|
||||||
|
<img class="h-14 w-14 rounded-md object-cover bg-base-200" src="{{ cart_item.product.images.all.0.s.url }}" alt="{{ cart_item.product.name }}">
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<div class="flex-1 min-w-0">
|
||||||
|
<div class="flex">
|
||||||
<a href="{% url 'web:product_detail' pk=cart_item.product.pk slug=cart_item.product.slug %}"
|
<a href="{% url 'web:product_detail' pk=cart_item.product.pk slug=cart_item.product.slug %}"
|
||||||
class="text-sm font-semibold leading-none hover:underline">
|
class="text-sm font-semibold leading-snug hover:text-primary line-clamp-2">
|
||||||
{{ cart_item.product.name }}
|
{{ cart_item.product.name }}
|
||||||
</a>
|
</a>
|
||||||
{% if cart_item.variant %}
|
{% if cart_item.variant %}
|
||||||
<p class="text-xs">
|
<p class="text-xs text-base-content/60">
|
||||||
{% for attribute_value in cart_item.variant.attribute_values.all %}{{ attribute_value }}{% if not forloop.last %}, {% endif %}{% endfor %}
|
{% for attribute_value in cart_item.variant.attribute_values.all %}{{ attribute_value }}{% if not forloop.last %}, {% endif %}{% endfor %}
|
||||||
</p>
|
</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<div class="flex items-center justify-between gap-2 mt-1">
|
||||||
|
<span class="text-xs text-base-content/60 mx-2">{% translate 'x' %} {{ cart_item.quantity }}</span>
|
||||||
|
<span class="text-sm font-bold">{{ cart_item.price.price_with_tax }} €</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="flex items-center justify-between gap-6">
|
<form hx-post="{% url 'web:delete_cart_item' pk=cart_item.pk %}" hx-swap="none">
|
||||||
<p
|
|
||||||
class="mt-0.5 truncate text-sm font-normal ">
|
|
||||||
{{ cart_item.price.price_with_tax }}€
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<form hx-post="{% url 'web:delete_cart_item' pk=cart_item.pk %}"
|
|
||||||
hx-swap="none">
|
|
||||||
<span class="mt-0.5 truncate text-sm font-normal mr-2">
|
|
||||||
{% translate 'Cantidad' %}: {{ cart_item.quantity }}
|
|
||||||
|
|
||||||
</span>
|
|
||||||
<button data-tooltip-target="tooltipRemoveItem1a" type="submit"
|
|
||||||
class="text-red-600 hover:text-red-700 :text-red-600 cursor-pointer"
|
|
||||||
>
|
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<span class="sr-only">{% translate 'Quitar' %}</span>
|
<button type="submit" class="btn btn-ghost btn-xs btn-circle text-error" aria-label="{% translate 'Quitar' %}">
|
||||||
{% include 'components/icons/remove.svg' %}
|
{% include 'components/icons/remove.svg' %}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<div id="tooltipRemoveItem1a" role="tooltip"
|
|
||||||
class="tooltip invisible absolute z-10 inline-block rounded-lg px-3 py-2 text-sm font-medium
|
|
||||||
text-white opacity-0 shadow-md transition-opacity duration-300 "
|
|
||||||
>
|
|
||||||
{% translate 'Quitar del carrito' %}
|
|
||||||
<div class="tooltip-arrow" data-popper-arrow></div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</li>
|
||||||
</div>
|
|
||||||
<hr class="h-px mx-4 my-2 " />
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</ul>
|
||||||
|
|
||||||
{% if cart.items.count > 0 %}
|
<a href="{% url 'web:cart_detail' %}" class="btn btn-primary btn-sm w-full mt-4">
|
||||||
<a href="{% url 'web:cart_detail' %}"
|
{% translate 'Ver carrito' %}
|
||||||
class="btn btn-primary"
|
|
||||||
role="button"> {% translate 'Ver carrito' %}
|
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|||||||
@@ -1,19 +1,33 @@
|
|||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load static %}
|
{% load static %}
|
||||||
<nav class="navbar">
|
<nav class="navbar sticky top-0 z-30 bg-base-100/90 backdrop-blur border-b border-base-300 px-4 sm:px-6 lg:px-8">
|
||||||
<div class="text-base-content">
|
<div class="flex-1">
|
||||||
<a href="{% url 'web:index' %}" class="flex text-xl">
|
<a href="{% url 'web:index' %}" class="flex items-center gap-2 text-lg sm:text-xl font-display font-bold text-base-content">
|
||||||
<img class="mr-4" src="{{ logo }}" alt="{{ web_title }} logo">
|
{% if logo %}
|
||||||
|
<img class="h-8 w-8 rounded-md object-cover" src="{{ logo }}" alt="{{ web_title }}">
|
||||||
|
{% endif %}
|
||||||
{{ web_title }}
|
{{ web_title }}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex gap-2">
|
<div class="flex items-center gap-1 sm:gap-2">
|
||||||
{% include 'components/generic/theme-switch.html' %}
|
{% include 'components/generic/theme-switch.html' %}
|
||||||
|
|
||||||
|
<div class="dropdown dropdown-end">
|
||||||
|
<div tabindex="0" role="button" class="btn btn-ghost btn-circle" aria-label="{% translate 'Carrito' %}">
|
||||||
|
{% include 'components/icons/cart.svg' %}
|
||||||
|
</div>
|
||||||
|
<div tabindex="-1" class="dropdown-content menu z-20 mt-3 w-80 rounded-box bg-base-100 p-4 shadow-lg border border-base-300">
|
||||||
|
<div hx-get="{% url 'web:cart_dropdown' %}" hx-trigger="load, updated-cart from:body" hx-swap="innerHTML">
|
||||||
|
{% include 'components/generic/spinner.html' %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{% if user.is_authenticated %}
|
{% if user.is_authenticated %}
|
||||||
{% include 'components/generic/user_dropdown.html' %}
|
{% include 'components/generic/user_dropdown.html' %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="{% url 'users:login' %}" class="link-button flex items-center">
|
<a href="{% url 'users:login' %}" class="btn btn-primary btn-sm sm:btn-md ml-1">
|
||||||
{% translate 'Inicia sesión' %}
|
{% translate 'Inicia sesión' %}
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
id="theme-toggle"
|
id="theme-toggle"
|
||||||
type="button"
|
type="button"
|
||||||
aria-label="switchtheme"
|
aria-label="switchtheme"
|
||||||
class="btn btn-circle">
|
class="btn btn-ghost btn-circle">
|
||||||
{% include 'components/icons/moon.svg' %}
|
{% include 'components/icons/moon.svg' %}
|
||||||
{% include 'components/icons/sun.svg' %}
|
{% include 'components/icons/sun.svg' %}
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -1,19 +1,32 @@
|
|||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
<div class="dropdown dropdown-end">
|
<div class="dropdown dropdown-end">
|
||||||
<div tabindex="0" role="button" class="btn btn-circle avatar">
|
<div tabindex="0" role="button" class="btn btn-ghost btn-circle avatar">
|
||||||
<div class="w-10 flex rounded-full justify-center items-center">
|
<div class="w-9 flex rounded-full bg-primary text-primary-content justify-center items-center font-semibold">
|
||||||
{{ request.user.first_name.0 | upper }}{{ request.user.last_name.0 | upper }}
|
{{ request.user.first_name.0 | upper }}{{ request.user.last_name.0 | upper }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ul
|
<ul
|
||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
class="menu menu-sm dropdown-content bg-base-100 rounded-box z-1 mt-3 w-52 p-2 shadow">
|
class="menu menu-sm dropdown-content bg-base-100 rounded-box z-20 mt-3 w-56 p-2 shadow-lg border border-base-300">
|
||||||
<li>
|
<li>
|
||||||
<a class="justify-between" href="{% url 'users:my_account' %}">
|
<a href="{% url 'users:my_account' %}">
|
||||||
{% trans 'Mi cuenta' %}
|
{% translate 'Mi cuenta' %}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{% url 'web:orders' %}">
|
||||||
|
{% translate 'Mis pedidos' %}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{% url 'web:wishlist' %}">
|
||||||
|
{% translate 'Lista de deseados' %}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="mt-1 border-t border-base-300 pt-1">
|
||||||
|
<a href="{% url 'users:logout' %}" class="text-error">
|
||||||
|
{% translate 'Cerrar sesión' %}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li><a>{% trans 'Ajustes' %}</a></li>
|
|
||||||
<li><a href="{% url 'users:logout' %}">{% trans 'Cerrar sesión' %}</a></li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
<svg class="-ms-2 me-2 h-5 w-5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24"
|
<svg class="h-4 w-4" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24"
|
||||||
height="24" fill="none" viewBox="0 0 24 24">
|
height="24" fill="none" viewBox="0 0 24 24">
|
||||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
d="M4 4h1.5L8 16m0 0h8m-8 0a2 2 0 1 0 0 4 2 2 0 0 0 0-4Zm8 0a2 2 0 1 0 0 4 2 2 0 0 0 0-4Zm.75-3H7.5M11 7H6.312M17 4v6m-3-3h6"/>
|
d="M4 4h1.5L8 16m0 0h8m-8 0a2 2 0 1 0 0 4 2 2 0 0 0 0-4Zm8 0a2 2 0 1 0 0 4 2 2 0 0 0 0-4Zm.75-3H7.5M11 7H6.312M17 4v6m-3-3h6"/>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 387 B After Width: | Height: | Size: 376 B |
@@ -1,23 +1,26 @@
|
|||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
<article class="card">
|
<article class="card bg-base-100 border border-base-300 rounded-2xl overflow-hidden h-full flex flex-col transition-shadow duration-200 hover:shadow-lg">
|
||||||
|
<a class="block aspect-square bg-base-200/50" href="{% url 'web:product_detail' pk=product.pk slug=product.slug %}">
|
||||||
<a class="h-56 w-full" href="{% url 'web:product_detail' pk=product.pk slug=product.slug %}">
|
<img class="h-full w-full object-contain p-4" src="{{ product.images.all.0.m.url }}" alt="{{ product.name }}" loading="lazy"/>
|
||||||
<img class="mx-auto h-full " src="{{ product.images.all.0.m.url }}" alt="{{ product.name }}"/>
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<div class="pt-6 flex justify-between">
|
<div class="p-4 flex flex-col flex-1">
|
||||||
<a href="{% url 'web:product_detail' pk=product.pk slug=product.slug %}" class="link">
|
<div class="flex items-start justify-between gap-2">
|
||||||
<h1>{{ product.name }}</h1>
|
<a href="{% url 'web:product_detail' pk=product.pk slug=product.slug %}" class="min-w-0">
|
||||||
|
<h2 class="font-display font-semibold leading-snug line-clamp-2 hover:text-primary transition-colors">
|
||||||
|
{{ product.name }}
|
||||||
|
</h2>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<p class="txt-2xl">
|
<p class="font-display font-bold text-lg whitespace-nowrap shrink-0">
|
||||||
{% with product.current_prices.0 as price %}
|
{% with product.current_prices.0 as price %}
|
||||||
{{ price.price_with_tax }} €
|
{{ price.price_with_tax }} €
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-4">
|
<div class="mt-auto pt-4">
|
||||||
{% include 'components/cart/add_to_cart.html' %}
|
{% include 'components/cart/add_to_cart.html' with size='sm' %}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
@@ -1,9 +1,5 @@
|
|||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
<section class=" flex items-center my-4">
|
<div class="mb-6">
|
||||||
<div class="max-w-screen-xl px-4 mx-auto lg:px-12 w-full">
|
|
||||||
<div class="relative shadow-md sm:rounded-lg">
|
|
||||||
<div class="flex flex-col items-center justify-between p-4 space-y-3 md:flex-row md:space-y-0 md:space-x-4">
|
|
||||||
<div class="w-full md:w-full">
|
|
||||||
<form class="flex items-center"
|
<form class="flex items-center"
|
||||||
hx-get="{% url 'web:list_products' %}"
|
hx-get="{% url 'web:list_products' %}"
|
||||||
hx-target="#products"
|
hx-target="#products"
|
||||||
@@ -11,15 +7,9 @@
|
|||||||
hx-swap="innerHTML"
|
hx-swap="innerHTML"
|
||||||
hx-push="true"
|
hx-push="true"
|
||||||
>
|
>
|
||||||
<label for="simple-search" class="input w-full">
|
<label for="simple-search" class="input input-bordered w-full max-w-md flex items-center gap-2">
|
||||||
<svg class="h-[1em] opacity-50" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
<svg class="h-4 w-4 opacity-50" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
<g
|
<g stroke-linejoin="round" stroke-linecap="round" stroke-width="2.5" fill="none" stroke="currentColor">
|
||||||
stroke-linejoin="round"
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-width="2.5"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
>
|
|
||||||
<circle cx="11" cy="11" r="8"></circle>
|
<circle cx="11" cy="11" r="8"></circle>
|
||||||
<path d="m21 21-4.3-4.3"></path>
|
<path d="m21 21-4.3-4.3"></path>
|
||||||
</g>
|
</g>
|
||||||
@@ -28,6 +18,7 @@
|
|||||||
type="search"
|
type="search"
|
||||||
name="name"
|
name="name"
|
||||||
id="simple-search"
|
id="simple-search"
|
||||||
|
class="grow"
|
||||||
placeholder="{% translate 'Buscar' %}"
|
placeholder="{% translate 'Buscar' %}"
|
||||||
autocomplete="off">
|
autocomplete="off">
|
||||||
</label>
|
</label>
|
||||||
@@ -36,8 +27,4 @@
|
|||||||
<input type="hidden" name="category" value="{{ category.id }}">
|
<input type="hidden" name="category" value="{{ category.id }}">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<form action="" hx-post="{% url 'web:delete_from_wishlist' pk=product.pk %}" hx-swap="none">
|
<form action="" hx-post="{% url 'web:delete_from_wishlist' pk=product.pk %}" hx-swap="none">
|
||||||
<input type="hidden" name="product" value="{{ product.pk }}">
|
<input type="hidden" name="product" value="{{ product.pk }}">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<button class="cursor-pointer" aria-label="dislike">
|
<button class="btn btn-outline btn-circle text-error border-error/40" aria-label="dislike">
|
||||||
{% include 'components/icons/liked.svg' %}
|
{% include 'components/icons/liked.svg' %}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
<form action="" hx-post="{% url 'web:add_to_wishlist' %}" hx-swap="none">
|
<form action="" hx-post="{% url 'web:add_to_wishlist' %}" hx-swap="none">
|
||||||
<input type="hidden" name="product" value="{{ product.pk }}">
|
<input type="hidden" name="product" value="{{ product.pk }}">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<button class="cursor-pointer" aria-label="like">
|
<button class="btn btn-outline btn-circle" aria-label="like">
|
||||||
{% include 'components/icons/like.svg' %}
|
{% include 'components/icons/like.svg' %}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
{% load i18n %}
|
|
||||||
<ul class="p-2 text-start text-sm font-medium ">
|
|
||||||
<li>
|
|
||||||
<a href="{% url 'users:my_account' %}" title=""
|
|
||||||
class="inline-flex w-full items-center gap-2 rounded-md px-3 py-2 text-sm hover: :">
|
|
||||||
{% translate 'Mi cuenta' %}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="{% url 'web:orders' %}" title=""
|
|
||||||
class="inline-flex w-full items-center gap-2 rounded-md px-3 py-2 text-sm hover: :">
|
|
||||||
{% translate 'Mis pedidos' %}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="{% url 'web:wishlist' %}" title=""
|
|
||||||
class="inline-flex w-full items-center gap-2 rounded-md px-3 py-2 text-sm hover: :">
|
|
||||||
{% translate 'Lista de deseados' %}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<div class="p-2 text-sm font-medium ">
|
|
||||||
<a href="{% url 'users:logout' %}" title=""
|
|
||||||
class="inline-flex w-full items-center gap-2 rounded-md px-3 py-2 text-sm hover: :">
|
|
||||||
{% translate 'Cerrar sesión' %}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{% load static %}
|
{% load static %}
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="es">
|
<html lang="es" data-theme="shoppy">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||||
@@ -12,16 +12,25 @@
|
|||||||
<link rel="shortcut icon" type="image/png" href="{{ favicon }}"/>
|
<link rel="shortcut icon" type="image/png" href="{{ favicon }}"/>
|
||||||
<script src="https://unpkg.com/htmx.org@2.0.3"></script>
|
<script src="https://unpkg.com/htmx.org@2.0.3"></script>
|
||||||
|
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@500;600;700;800&display=swap" rel="stylesheet">
|
||||||
|
|
||||||
<link href="https://cdn.jsdelivr.net/npm/daisyui@5" rel="stylesheet" type="text/css" />
|
<link href="https://cdn.jsdelivr.net/npm/daisyui@5" rel="stylesheet" type="text/css" />
|
||||||
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
|
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
|
||||||
<link href="https://cdn.jsdelivr.net/npm/daisyui@5/themes.css" rel="stylesheet" type="text/css" />
|
<link href="https://cdn.jsdelivr.net/npm/daisyui@5/themes.css" rel="stylesheet" type="text/css" />
|
||||||
|
<style type="text/tailwindcss">
|
||||||
|
@theme {
|
||||||
|
--font-display: "Outfit", ui-sans-serif, system-ui, sans-serif;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<link rel="stylesheet" href="{% static 'css/theme.css' %}">
|
||||||
|
|
||||||
<link rel="stylesheet" href="{% static 'css/styles.css' %}">
|
|
||||||
{% block extra_js %}
|
{% block extra_js %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body class="bg-base-100 text-base-content antialiased min-h-screen flex flex-col">
|
||||||
<main>
|
<main class="flex-1">
|
||||||
{% block main %}
|
{% block main %}
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
@import "tailwindcss";
|
|
||||||
|
|
||||||
|
|
||||||
@theme {
|
|
||||||
--font-display: "Satoshi", "sans-serif";
|
|
||||||
--breakpoint-3xl: 1920px;
|
|
||||||
|
|
||||||
--ease-fluid: cubic-bezier(0.3, 0, 0, 1);
|
|
||||||
--ease-snappy: cubic-bezier(0.2, 0, 0, 1); /* ... */
|
|
||||||
|
|
||||||
{% for color in colors %}
|
|
||||||
--color-{{ color.name }}-{{ color.index }}: {{ color.value }};
|
|
||||||
{% endfor %}
|
|
||||||
}
|
|
||||||
|
|
||||||
@variant dark (&:where(.dark, .dark *));
|
|
||||||
@@ -3,10 +3,9 @@
|
|||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
{% include 'components/generic/navbar.html' %}
|
{% include 'components/generic/navbar.html' %}
|
||||||
<div class="mt-24">
|
<div class="max-w-screen-xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
|
||||||
{% include 'components/products/list_filters.html' %}
|
{% include 'components/products/list_filters.html' %}
|
||||||
<section
|
<section
|
||||||
class="px-8"
|
|
||||||
hx-get="
|
hx-get="
|
||||||
{% url 'web:list_products' %}{% querystring request.GET %}{% if filter_by_category %}{% querystring category=category.id %}{% endif %}"
|
{% url 'web:list_products' %}{% querystring request.GET %}{% if filter_by_category %}{% querystring category=category.id %}{% endif %}"
|
||||||
hx-trigger="load"
|
hx-trigger="load"
|
||||||
@@ -14,14 +13,10 @@
|
|||||||
hx-swap="innerHTML"
|
hx-swap="innerHTML"
|
||||||
>
|
>
|
||||||
<section id="products">
|
<section id="products">
|
||||||
<div class="flex justify-center items-center">
|
<div class="flex justify-center items-center py-16">
|
||||||
{% include 'components/generic/spinner.html' %}
|
{% include 'components/generic/spinner.html' %}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<div class="w-full text-center">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -1,17 +1,22 @@
|
|||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load static %}
|
{% load static %}
|
||||||
|
|
||||||
<ul class="product-grid">
|
<ul class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4 sm:gap-6 mb-8">
|
||||||
{% for product in page %}
|
{% for product in page %}
|
||||||
<li>
|
<li>
|
||||||
{% include 'components/product_card.html' %}
|
{% include 'components/product_card.html' %}
|
||||||
</li>
|
</li>
|
||||||
|
{% empty %}
|
||||||
|
<li class="col-span-full text-center py-16 text-base-content/60">
|
||||||
|
{% translate 'No se han encontrado productos.' %}
|
||||||
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div class="flex justify-center items-center">
|
<div class="flex justify-center items-center gap-2 pb-4">
|
||||||
{% if has_previous_page %}
|
{% if has_previous_page %}
|
||||||
<button type="button"
|
<button type="button"
|
||||||
|
class="btn btn-outline btn-sm"
|
||||||
hx-get="{% url 'web:list_products' %}{% querystring page=page.previous_page_number %}"
|
hx-get="{% url 'web:list_products' %}{% querystring page=page.previous_page_number %}"
|
||||||
hx-trigger="click"
|
hx-trigger="click"
|
||||||
hx-target="#products"
|
hx-target="#products"
|
||||||
@@ -20,8 +25,12 @@
|
|||||||
{% translate 'Anterior' %}
|
{% translate 'Anterior' %}
|
||||||
</button>
|
</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<span class="text-sm text-base-content/60 px-2">
|
||||||
|
{% blocktranslate %}Página {{ current_page }} de {{ num_pages }}{% endblocktranslate %}
|
||||||
|
</span>
|
||||||
{% if has_next_page %}
|
{% if has_next_page %}
|
||||||
<button type="button"
|
<button type="button"
|
||||||
|
class="btn btn-outline btn-sm"
|
||||||
hx-get="{% url 'web:list_products' %}{% querystring page=page.next_page_number %}"
|
hx-get="{% url 'web:list_products' %}{% querystring page=page.next_page_number %}"
|
||||||
hx-trigger="click"
|
hx-trigger="click"
|
||||||
hx-target="#products"
|
hx-target="#products"
|
||||||
@@ -30,8 +39,4 @@
|
|||||||
{% translate 'Siguiente' %}
|
{% translate 'Siguiente' %}
|
||||||
</button>
|
</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<span class="page">
|
|
||||||
{% blocktranslate %}Página {{ current_page }} de {{ num_pages }}{% endblocktranslate %}
|
|
||||||
</span>
|
|
||||||
|
|||||||
+72
-119
@@ -3,163 +3,117 @@
|
|||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
{% include 'components/generic/navbar.html' %}
|
{% include 'components/generic/navbar.html' %}
|
||||||
{% load i18n %}
|
<section class="py-6 md:py-12 antialiased">
|
||||||
<section class=" py-2 antialiased md:py-8">
|
<div class="max-w-screen-xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="mx-auto max-w-screen-xl px-4 2xl:px-0">
|
<h2 class="text-xl sm:text-2xl font-display font-bold flex items-center gap-3 mb-6">
|
||||||
<h2 class="text-xl font-semibold sm:text-2xl">
|
|
||||||
{% translate 'Resumen del pedido' %}
|
{% translate 'Resumen del pedido' %}
|
||||||
|
|
||||||
{% if order.status == 'PAI' %}
|
{% if order.status == 'PAI' %}
|
||||||
<span class=" text-green-800 text-sm font-medium me-2 px-2.5 py-0.5 rounded ml-3">{% trans 'Pagado' %}</span>
|
<span class="badge badge-success">{% trans 'Pagado' %}</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<div class="mt-4 sm:mt-6 md:gap-6 lg:flex lg:items-start xl:gap-8">
|
<div class="lg:grid lg:grid-cols-3 lg:gap-8 xl:gap-12">
|
||||||
<div class="mx-auto w-full flex-none lg:max-w-2xl xl:max-w-4xl">
|
<div class="lg:col-span-2 flex flex-col gap-4">
|
||||||
<div class="space-y-6">
|
|
||||||
|
|
||||||
{% for item in items %}
|
{% for item in items %}
|
||||||
<div
|
<div class="rounded-2xl border border-base-300 bg-base-100 p-4 md:p-6 flex items-center gap-4">
|
||||||
class="rounded-lg p-4 shadow-md md:p-6">
|
<a href="#" class="shrink-0">
|
||||||
<div class="space-y-4 md:flex md:items-center md:justify-between md:gap-6 md:space-y-0">
|
<img class="h-20 w-20 rounded-lg object-contain bg-base-200/50 p-1" src="{{ item.product.images.all.0.s.url }}"
|
||||||
<a href="#" class="shrink-0 md:order-1">
|
|
||||||
<img class="h-20 w-20 " src="{{ item.product.images.all.0.s.url }}"
|
|
||||||
alt="{{ item.product.name }}"/>
|
|
||||||
<img class="hidden h-20 w-20 " src="{{ item.product.images.all.0.s_dark.url }}"
|
|
||||||
alt="{{ item.product.name }}"/>
|
alt="{{ item.product.name }}"/>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<div class="flex items-center justify-between md:order-3 md:justify-end">
|
<div class="flex-1 min-w-0">
|
||||||
<div class="flex items-center">
|
|
||||||
<span
|
|
||||||
class="w-10 shrink-0 text-center text-sm font-medium focus:outline-none focus:ring-0 ">
|
|
||||||
{{ item.quantity|floatformat }}x
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="text-end md:order-4 md:w-32">
|
|
||||||
<p
|
|
||||||
class="text-base font-bold ">
|
|
||||||
{{ item.product.price.price_with_tax }}€
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="w-full min-w-0 flex-1 space-y-4 md:order-2 md:max-w-md">
|
|
||||||
<a href="{% url 'web:product_detail' pk=item.product.pk slug=item.product.slug %}"
|
<a href="{% url 'web:product_detail' pk=item.product.pk slug=item.product.slug %}"
|
||||||
class="text-base font-medium hover:underline "
|
class="text-base font-medium hover:text-primary"
|
||||||
>
|
>
|
||||||
{{ item.product.name }}
|
{{ item.product.name }}
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="text-end shrink-0">
|
||||||
|
<span class="block text-sm text-base-content/60 mb-1">{{ item.quantity|floatformat }}x</span>
|
||||||
|
<p class="text-base font-bold">{{ item.product.price.price_with_tax }}€</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
{% if items.count == 0 %}
|
{% if items.count == 0 %}
|
||||||
<p class="text-base font-normal ">
|
<div class="rounded-2xl border border-base-300 bg-base-100 p-8 text-center">
|
||||||
{% translate 'No hay nada en el carrito...' %}
|
<p class="text-base-content/70 mb-2">{% translate 'No hay nada en el carrito...' %}</p>
|
||||||
</p>
|
<a href="{% url 'web:index' %}" class="link link-primary">
|
||||||
<p>
|
|
||||||
<a href="{% url 'web:index' %}" title=""
|
|
||||||
class="inline-flex items-center gap-2 text-sm font-medium text-primary-700 underline hover:no-underline ">
|
|
||||||
{% translate 'Volver a inicio' %}
|
{% translate 'Volver a inicio' %}
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<section>
|
<section class="rounded-2xl border border-base-300 bg-base-100 p-4 md:p-6">
|
||||||
<h2 class="text-xl font-semibold sm:text-2xl">
|
<h2 class="text-lg font-display font-semibold mb-2">
|
||||||
{% translate 'Dirección de envío' %}
|
{% translate 'Dirección de envío' %}
|
||||||
</h2>
|
</h2>
|
||||||
|
<div class="text-sm text-base-content/80 flex flex-col gap-0.5">
|
||||||
<div>
|
<p>{{ order.email }}</p>
|
||||||
<p class="text-m ">{{ order.email }}</p>
|
<p>{{ order.shipping_address }}</p>
|
||||||
<p class="text-m ">{{ order.shipping_address }}</p>
|
<p>{{ order.shipping_city }}</p>
|
||||||
<p class="text-m ">{{ order.shipping_city }}</p>
|
<p>{{ order.shipping_state }}</p>
|
||||||
<p class="text-m ">{{ order.shipping_state }}</p>
|
<p>{{ order.shipping_country }}</p>
|
||||||
<p class="text-m ">{{ order.shipping_country }}</p>
|
<p>{{ order.shipping_zip }}</p>
|
||||||
<p class="text-m ">{{ order.shipping_zip }}</p>
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section>
|
<section class="rounded-2xl border border-base-300 bg-base-100 p-4 md:p-6">
|
||||||
<h2 class="text-xl font-semibold sm:text-2xl">
|
<h2 class="text-lg font-display font-semibold mb-2">
|
||||||
{% translate 'Dirección de facturación' %}
|
{% translate 'Dirección de facturación' %}
|
||||||
</h2>
|
</h2>
|
||||||
|
<div class="text-sm text-base-content/80 flex flex-col gap-0.5">
|
||||||
<div>
|
<p>{{ order.billing_address }}</p>
|
||||||
<p class="text-m ">{{ order.billing_address }}</p>
|
<p>{{ order.billing_city }}</p>
|
||||||
<p class="text-m ">{{ order.billing_city }}</p>
|
<p>{{ order.billing_state }}</p>
|
||||||
<p class="text-m ">{{ order.billing_state }}</p>
|
<p>{{ order.billing_country }}</p>
|
||||||
<p class="text-m ">{{ order.billing_country }}</p>
|
<p>{{ order.billing_zip }}</p>
|
||||||
<p class="text-m ">{{ order.billing_zip }}</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section>
|
<section class="rounded-2xl border border-base-300 bg-base-100 p-4 md:p-6">
|
||||||
<h2 class="text-xl font-semibold sm:text-2xl">
|
<h2 class="text-lg font-display font-semibold mb-2">
|
||||||
{% translate 'Método de envío' %}
|
{% translate 'Método de envío' %}
|
||||||
</h2>
|
</h2>
|
||||||
|
<p class="text-sm text-base-content/80">{{ order.shipping_method.name }}</p>
|
||||||
<p class="text-m ">{{ order.shipping_method.name }}</p>
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Resumen del pedido -->
|
<!-- Resumen del pedido -->
|
||||||
<div class="mx-auto mt-6 max-w-4xl flex-1 space-y-6 lg:mt-0 lg:w-full">
|
<div class="mt-6 lg:mt-0">
|
||||||
<div
|
<div class="rounded-2xl border border-base-300 bg-base-100 p-4 sm:p-6 sticky top-20">
|
||||||
class="space-y-4 rounded-lg p-4 shadow-md sm:p-6">
|
<p class="text-lg font-display font-semibold mb-4">
|
||||||
<p class="text-xl font-semibold ">
|
{% translate 'Resumen del pedido' %}
|
||||||
{% translate 'Resumen del pedido' %}</p>
|
</p>
|
||||||
|
|
||||||
<div class="space-y-4">
|
<div class="flex flex-col gap-2 text-sm">
|
||||||
<div class="space-y-2">
|
<div class="flex items-center justify-between">
|
||||||
<dl class="flex items-center justify-between gap-4">
|
<span class="text-base-content/70">{% translate 'Base imponible' %}</span>
|
||||||
<dt
|
<span class="font-medium">{{ base_total }} €</span>
|
||||||
class="text-base font-normal ">
|
|
||||||
{% translate 'Base imponible' %}
|
|
||||||
</dt>
|
|
||||||
<dd class="text-base font-medium ">{{ base_total }} €
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dl class="flex items-center justify-between gap-4">
|
|
||||||
<dt class="text-base font-normal ">
|
|
||||||
{% translate 'Descuentos' %}
|
|
||||||
</dt>
|
|
||||||
<dd class="text-base font-medium text-green-600">-{{ savings }} €</dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dl class="flex items-center justify-between gap-4">
|
|
||||||
<dt
|
|
||||||
class="text-base font-normal ">
|
|
||||||
{% translate 'Gastos de envío' %}
|
|
||||||
</dt>
|
|
||||||
<dd class="text-base font-medium ">{{ shipping_cost }}
|
|
||||||
€
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dl class="flex items-center justify-between gap-4">
|
|
||||||
<dt class="text-base font-normal ">
|
|
||||||
{% translate 'Impuestos' %}
|
|
||||||
</dt>
|
|
||||||
<dd class="text-base font-medium ">{{ tax_total }} €
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<dl class="flex items-center justify-between gap-4 pt-2 ">
|
<div class="flex items-center justify-between">
|
||||||
<dt class="text-base font-bold ">{% translate 'Total' %}
|
<span class="text-base-content/70">{% translate 'Descuentos' %}</span>
|
||||||
</dt>
|
<span class="font-medium text-success">-{{ savings }} €</span>
|
||||||
<dd class="text-base font-bold ">{{ total }} €</dd>
|
</div>
|
||||||
</dl>
|
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<span class="text-base-content/70">{% translate 'Gastos de envío' %}</span>
|
||||||
|
<span class="font-medium">{{ shipping_cost }} €</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<span class="text-base-content/70">{% translate 'Impuestos' %}</span>
|
||||||
|
<span class="font-medium">{{ tax_total }} €</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex items-center justify-between border-t border-base-300 mt-4 pt-4">
|
||||||
|
<span class="font-display font-bold">{% translate 'Total' %}</span>
|
||||||
|
<span class="font-display font-bold text-xl">{{ total }} €</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% if order.status == 'PEN' %}
|
{% if order.status == 'PEN' %}
|
||||||
@@ -169,14 +123,13 @@
|
|||||||
<input type="hidden" name="Ds_MerchantParameters" value="{{ merchant_parameters }}"/>
|
<input type="hidden" name="Ds_MerchantParameters" value="{{ merchant_parameters }}"/>
|
||||||
<input type="hidden" name="Ds_Signature" value="{{ signature }}"/>
|
<input type="hidden" name="Ds_Signature" value="{{ signature }}"/>
|
||||||
|
|
||||||
<button class="btn btn-primary">
|
<button class="btn btn-primary w-full mt-6">
|
||||||
{% translate 'Pagar' %}
|
{% translate 'Pagar' %}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
<div class="flex items-center justify-center gap-2">
|
<div class="flex items-center justify-center gap-2 mt-3">
|
||||||
<span class="text-sm font-normal "> {% translate 'o' %} </span>
|
<span class="text-sm text-base-content/60">{% translate 'o' %}</span>
|
||||||
<a href="{% url 'web:index' %}" title=""
|
<a href="{% url 'web:index' %}" class="link link-primary text-sm">
|
||||||
class="inline-flex items-center gap-2 text-sm font-medium text-primary-700 underline hover:no-underline ">
|
|
||||||
{% translate 'Seguir comprando' %}
|
{% translate 'Seguir comprando' %}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,98 +3,61 @@
|
|||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
{% include 'components/generic/navbar.html' %}
|
{% include 'components/generic/navbar.html' %}
|
||||||
<div class="mx-auto max-w-screen-xl px-4 2xl:px-0">
|
<div class="max-w-screen-xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
|
||||||
<div class="mx-auto max-w-5xl">
|
<div class="mx-auto max-w-5xl">
|
||||||
<div class="gap-4">
|
<h1 class="text-xl sm:text-2xl font-display font-bold mb-6">
|
||||||
<h1 class="text-xl font-semibold sm:text-2xl my-4">
|
|
||||||
{% translate 'Mis pedidos' %}
|
{% translate 'Mis pedidos' %}
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<div class="mt-6 flow-root sm:mt-8">
|
<div class="flex flex-col gap-4">
|
||||||
<div class="divide-y divide-gray-200 ">
|
|
||||||
{% for order in page %}
|
{% for order in page %}
|
||||||
|
<article class="rounded-2xl border border-base-300 bg-base-100 p-4 sm:p-6 flex flex-wrap items-center gap-4">
|
||||||
<article class="flex flex-wrap items-center gap-y-4 py-6">
|
<dl class="flex-1 min-w-[8rem]">
|
||||||
<dl class="w-1/2 sm:w-1/4 lg:w-auto lg:flex-1 px-4">
|
<dt class="text-xs text-base-content/60">{% translate 'Número de pedido' %}</dt>
|
||||||
<dt class="text-base font-medium ">
|
<dd class="font-semibold">
|
||||||
{% translate 'Número de pedido' %}
|
<a href="{% url 'web:order' uuid=order.uuid %}" class="hover:text-primary">
|
||||||
</dt>
|
|
||||||
<dd class="mt-1.5 text-base font-semibold ">
|
|
||||||
<a href="{% url 'web:order' uuid=order.uuid %}" class="hover:underline">
|
|
||||||
#{{ order.code }}
|
#{{ order.code }}
|
||||||
</a>
|
</a>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<dl class="w-1/2 sm:w-1/4 lg:w-auto lg:flex-1 px-4">
|
<dl class="flex-1 min-w-[8rem]">
|
||||||
<dt class="text-base font-medium ">
|
<dt class="text-xs text-base-content/60">{% translate 'Fecha' %}</dt>
|
||||||
{% translate 'Fecha' %}
|
<dd class="font-semibold">{{ order.creation_date }}</dd>
|
||||||
</dt>
|
|
||||||
<dd class="mt-1.5 text-base font-semibold ">
|
|
||||||
{{ order.creation_date }}
|
|
||||||
</dd>
|
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<dl class="w-1/2 sm:w-1/4 lg:w-auto lg:flex-1 px-4">
|
<dl class="flex-1 min-w-[6rem]">
|
||||||
<dt class="text-base font-medium ">
|
<dt class="text-xs text-base-content/60">{% translate 'Total' %}</dt>
|
||||||
{% translate 'Total' %}
|
<dd class="font-semibold">{{ order.total }}€</dd>
|
||||||
</dt>
|
|
||||||
<dd class="mt-1.5 text-base font-semibold ">
|
|
||||||
{{ order.total }}€
|
|
||||||
</dd>
|
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<dl class="w-1/2 sm:w-1/4 lg:w-auto lg:flex-1 px-4">
|
<div class="flex-1 min-w-[8rem] flex flex-wrap gap-1">
|
||||||
|
|
||||||
{% if order.status == 'PAI' %}
|
{% if order.status == 'PAI' %}
|
||||||
<dd class="inline-flex text-green-800 text-xs font-medium me-2 px-2.5 py-0.5 rounded ">
|
<span class="badge badge-success badge-sm">{% translate 'Pagado' %}</span>
|
||||||
{% translate 'Pagado' %}
|
|
||||||
</dd>
|
|
||||||
|
|
||||||
{% if order.shipping_status == 'NOT' %}
|
{% if order.shipping_status == 'NOT' %}
|
||||||
<dd class="inline-flex text-yellow-800 text-xs font-medium me-2 px-2.5 py-0.5 rounded ">
|
<span class="badge badge-warning badge-sm">{% translate 'Tramitado' %}</span>
|
||||||
{% translate 'Tramitado' %}
|
|
||||||
</dd>
|
|
||||||
{% elif order.shipping_status == 'RDY' %}
|
{% elif order.shipping_status == 'RDY' %}
|
||||||
<dd class="inline-flex text-yellow-800 text-xs font-medium me-2 px-2.5 py-0.5 rounded ">
|
<span class="badge badge-warning badge-sm">{% translate 'Preparado' %}</span>
|
||||||
{% translate 'Preparado' %}
|
|
||||||
</dd>
|
|
||||||
{% elif order.shipping_status == 'TBS' %}
|
{% elif order.shipping_status == 'TBS' %}
|
||||||
<dd class="inline-flex text-yellow-800 text-xs font-medium me-2 px-2.5 py-0.5 rounded ">
|
<span class="badge badge-warning badge-sm">{% translate 'Listo' %}</span>
|
||||||
{% translate 'Listo' %}
|
|
||||||
</dd>
|
|
||||||
{% elif order.shipping_status == 'SNT' %}
|
{% elif order.shipping_status == 'SNT' %}
|
||||||
<dd class="inline-flex text-blue-800 text-xs font-medium me-2 px-2.5 py-0.5 rounded ">
|
<span class="badge badge-info badge-sm">{% translate 'Enviado' %}</span>
|
||||||
{% translate 'Enviado' %}
|
|
||||||
</dd>
|
|
||||||
{% elif order.shipping_status == 'DLV' %}
|
{% elif order.shipping_status == 'DLV' %}
|
||||||
<dd class="inline-flex text-green-800 text-xs font-medium me-2 px-2.5 py-0.5 rounded ">
|
<span class="badge badge-success badge-sm">{% translate 'Entregado' %}</span>
|
||||||
{% translate 'Entregado' %}
|
|
||||||
</dd>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% elif order.status == 'ERR' %}
|
{% elif order.status == 'ERR' %}
|
||||||
<dd class="inline-flex text-red-800 text-xs font-medium me-2 px-2.5 py-0.5 rounded ">
|
<span class="badge badge-error badge-sm">{% translate 'Error' %}</span>
|
||||||
{% translate 'Error' %}
|
|
||||||
</dd>
|
|
||||||
{% elif order.status == 'RTN' %}
|
{% elif order.status == 'RTN' %}
|
||||||
<dd class="inline-flex text-yellow-800 text-xs font-medium me-2 px-2.5 py-0.5 rounded ">
|
<span class="badge badge-warning badge-sm">{% translate 'Devuelto' %}</span>
|
||||||
{% translate 'Devuelto' %}
|
|
||||||
</dd>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</dl>
|
</div>
|
||||||
|
|
||||||
<a href="{% url 'web:order' uuid=order.uuid %}"
|
<a href="{% url 'web:order' uuid=order.uuid %}" class="btn btn-outline btn-sm w-full lg:w-auto">
|
||||||
class="w-full inline-flex justify-center rounded-lg px-3 py-2 text-sm font-medium hover: hover:text-primary-700 focus:z-10 focus:outline-none focus:ring-4 focus:ring-gray-100 : :text-white :ring-gray-700 lg:w-auto">
|
|
||||||
{% translate 'Ver pedido' %}
|
{% translate 'Ver pedido' %}
|
||||||
</a>
|
</a>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -6,64 +6,73 @@
|
|||||||
{% block main %}
|
{% block main %}
|
||||||
{% include 'components/generic/navbar.html' %}
|
{% include 'components/generic/navbar.html' %}
|
||||||
|
|
||||||
<section class="min-w-full py-8 md:py-16 antialiased">
|
<section class="py-6 md:py-12 antialiased">
|
||||||
<div class="max-w-screen-xl px-4 mx-auto 2xl:px-0">
|
<div class="max-w-screen-xl px-4 sm:px-6 lg:px-8 mx-auto">
|
||||||
<div class="lg:grid lg:grid-cols-2 lg:gap-8 xl:gap-16">
|
<div class="lg:grid lg:grid-cols-2 lg:gap-8 xl:gap-16">
|
||||||
<div class="shrink-0 max-w-md lg:max-w-lg mx-auto">
|
<div class="shrink-0 max-w-md lg:max-w-lg mx-auto w-full">
|
||||||
|
|
||||||
<div class="carousel w-full">
|
<div class="carousel w-full rounded-2xl bg-base-200/50 aspect-square">
|
||||||
{% for image in product.images.all %}
|
{% for image in product.images.all %}
|
||||||
|
<div id="product-image-{{ forloop.counter }}" class="carousel-item w-full items-center justify-center">
|
||||||
<div id="product-image-{{ forloop.counter }}" class="carousel-item w-full">
|
<img class="w-full h-full object-contain p-6" src="{{ image.xl.url }}" alt="{{ product.name }}"/>
|
||||||
<img class="carousel-item w-full " src="{{ image.xl.url }}"
|
|
||||||
alt="{{ product.name }}"/>
|
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="flex w-full justify-center gap-2 py-2">
|
|
||||||
{% for image in product.images.all %}
|
|
||||||
<a href="#product-image-{{ forloop.counter }}" class="btn btn-xs">{{ forloop.counter }}</a>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{% if product.images.all|length > 1 %}
|
||||||
|
<div class="flex w-full justify-center gap-2 py-3 flex-wrap">
|
||||||
|
{% for image in product.images.all %}
|
||||||
|
<a href="#product-image-{{ forloop.counter }}" class="w-14 h-14 rounded-lg border-2 border-base-300 hover:border-primary overflow-hidden shrink-0">
|
||||||
|
<img class="w-full h-full object-contain bg-base-200/50 p-1" src="{{ image.s.url }}" alt="{{ product.name }} {{ forloop.counter }}">
|
||||||
|
</a>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="my-4 sm:m-8 lg:m-0">
|
<div class="mt-6 lg:mt-0">
|
||||||
|
<h1 class="font-display text-2xl sm:text-3xl font-bold text-base-content">
|
||||||
<h1 class="text-xl font-semibold sm:text-2xl ">
|
|
||||||
{{ product.name }}
|
{{ product.name }}
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<div class="my-4 sm:items-center sm:gap-4 sm:flex">
|
<div class="my-4 flex items-center gap-3 flex-wrap">
|
||||||
<p
|
<p class="font-display text-3xl sm:text-4xl font-extrabold">
|
||||||
class="text-2xl font-extrabold sm:text-3xl "
|
|
||||||
>
|
|
||||||
{% if product.price %}
|
{% if product.price %}
|
||||||
{{ product.price.price_with_tax }} €
|
{{ product.price.price_with_tax }} €
|
||||||
{% elif product.min_variant_price %}
|
{% elif product.min_variant_price %}
|
||||||
{% translate 'Desde' %} {{ product.min_variant_price.price_with_tax }} €
|
{% translate 'Desde' %} {{ product.min_variant_price.price_with_tax }} €
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
{% if not product.has_variants %}
|
||||||
|
{% if product.stock > 0 %}
|
||||||
|
<span class="badge badge-success badge-outline">{% translate 'En stock' %}</span>
|
||||||
|
{% else %}
|
||||||
|
<span class="badge badge-error badge-outline">{% translate 'Agotado' %}</span>
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="my-4 sm:gap-4 items-center flex sm:m-8">
|
<hr class="my-6 border-base-300"/>
|
||||||
|
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
{% if user.is_authenticated %}
|
{% if user.is_authenticated %}
|
||||||
<div class="mr-2" hx-get="{% url 'web:wishlist_button' pk=product.pk %}"
|
<div hx-get="{% url 'web:wishlist_button' pk=product.pk %}" hx-trigger="load, updated-wishlist">
|
||||||
hx-trigger="load, updated-wishlist">
|
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
<div class="flex-1 max-w-xs">
|
||||||
{% include 'components/cart/add_to_cart.html' %}
|
{% include 'components/cart/add_to_cart.html' %}
|
||||||
|
|
||||||
<hr class="my-6 md:my-8 "/>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<p class="mb-6 ">
|
</div>
|
||||||
|
|
||||||
|
<hr class="my-6 border-base-300"/>
|
||||||
|
|
||||||
|
<p class="text-base-content/80 leading-relaxed whitespace-pre-line">
|
||||||
{{ product.description }}
|
{{ product.description }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -44,7 +44,9 @@ class ListProducts(TemplateView, FilteredQuerysetMixin, PaginatedQuerysetMixin):
|
|||||||
|
|
||||||
class ListWishlistedProducts(TemplateView, FilteredQuerysetMixin, PaginatedQuerysetMixin):
|
class ListWishlistedProducts(TemplateView, FilteredQuerysetMixin, PaginatedQuerysetMixin):
|
||||||
template_name = 'web/list_products.html'
|
template_name = 'web/list_products.html'
|
||||||
queryset = Product.objects.filter(hidden=False).prefetch_related('images')
|
queryset = Product.objects.filter(hidden=False).prefetch_related(
|
||||||
|
'images', Prefetch('prices', queryset=ProductPrice.objects.filter(current=True), to_attr='current_prices')
|
||||||
|
)
|
||||||
filter_class = ProductFilter
|
filter_class = ProductFilter
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
|
|||||||
Reference in New Issue
Block a user