Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified essenza/db.sqlite3
Binary file not shown.
5 changes: 3 additions & 2 deletions essenza/essenza/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'DIRS': [ BASE_DIR / 'templates' ],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
Expand Down Expand Up @@ -119,11 +119,12 @@
# https://docs.djangoproject.com/en/5.2/howto/static-files/

STATIC_URL = 'static/'

STATICFILES_DIRS = [BASE_DIR / 'static']
# Default primary key field type
# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

# -----------------------------------------------------------------
# SOLUCIÓN AL ERROR E304
# Especifica que nuestro modelo 'Usuario' en la app 'user'
Expand Down
51 changes: 36 additions & 15 deletions essenza/essenza/urls.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from django.contrib import admin
from django.urls import path
from django.urls import path, include
from django.http import HttpResponse
from info import views

Expand All @@ -15,8 +15,7 @@ def home(request):
text-align: center;
padding-top: 100px;
color: #444;
/* Aseguramos que el cuerpo permita posicionamiento absoluto para el botón */
position: relative;
position: relative;
}
h1 {
color: #c06b3e;
Expand All @@ -27,36 +26,55 @@ def home(request):
font-size: 20px;
color: #555;
}
/* Estilo para el botón de Información (simulando la 'i' del mockup) */
.info-button {
position: absolute;
top: 20px; /* Distancia desde la parte superior */
left: 20px; /* Distancia desde la izquierda */
top: 20px;
left: 20px;
width: 30px;
height: 30px;
background-color: #c06b3e; /* Color corporativo o distintivo */
border-radius: 50%; /* Forma circular */
background-color: #c06b3e;
border-radius: 50%;
text-align: center;
line-height: 30px; /* Centra verticalmente la 'i' */
line-height: 30px;
font-size: 18px;
font-weight: bold;
color: white;
text-decoration: none; /* Elimina el subrayado del enlace */
text-decoration: none;
cursor: pointer;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
transition: background-color 0.3s;
}
.info-button:hover {
background-color: #a35a34; /* Oscurece al pasar el ratón */
.info-button:hover { background-color: #a35a34; }
.login-button {
position: absolute;
top: 60%;
left: 50%;
transform: translate(-50%, -50%);
padding: 15px 35px;
background-color: #c06b3e;
color: white;
font-size: 20px;
font-weight: bold;
border: none;
border-radius: 10px;
cursor: pointer;
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
text-decoration: none;
transition: background-color 0.3s, transform 0.2s;
}
.login-button:hover {
background-color: #a35a34;
transform: translate(-50%, -50%) scale(1.05);
}
</style>
</head>
<body>
<a href="/info/" class="info-button" title="Información Legal y Contacto">i</a>
<h1>Bienvenidos a Essenza</h1>
<p>Tu espacio online de cosmética natural, belleza y cuidado personal.</p>
<p>Explora nuestros productos, descubre nuevas fragancias y disfruta de la experiencia Essenza 🌸</p>
<a href="/user/login" class="login-button" title="Iniciar Sesión">Iniciar sesión</a>
</body>
</html>
"""
Expand All @@ -65,6 +83,9 @@ def home(request):
urlpatterns = [
path('', home, name='home'),
path('info/', views.info_view, name='info-home'),
path('admin/', admin.site.urls),
path("user/", include("user.urls")),
path('user/login/', include('user.urls')),
path("accounts/", include("django.contrib.auth.urls")),
path('admin/', admin.site.urls)
]

97 changes: 97 additions & 0 deletions essenza/templates/user/login.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
{% load static %}
<!doctype html>
<html lang="es">
<head>
<meta charset="utf-8">
<title>Iniciar sesión · Essenza</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body.login-bg {
background-color: #faf7f2;
margin:0;
font-family:'Segoe UI', Arial, sans-serif;
}

.page{
min-height:100dvh;
display:grid;
place-items:start center;
padding-top:56px;
}

.brand{
color: #c06b3e;
font-size: 48px;
margin-bottom: 10px;
}

.login-card{
width:min(420px, 88vw);
background:#fff;
border: 2px solid #c06b3e;
border-radius:16px;
box-shadow:0 12px 28px rgba(0,0,0,.06);
padding:22px 24px;
}

label{ display:block; font-size:13px; color:#333; margin:10px 0 6px; }

input[type="text"], input[type="email"], input[type="password"]{
width:90%; padding:10px 12px; border:1px solid #eee; border-radius:10px;
background:#fafafa; outline:none;
}

input:focus{
border-color:#c06b3e;
box-shadow:0 0 0 3px rgba(192, 107, 62, 0.2);
}

.btn-primary{
width:100%; margin-top:14px; padding:10px 12px; border-radius:10px;
background: #c06b3e;
color:#fff; border:none; cursor:pointer;
transition: background-color 0.3s; /* Añadida transición */
}

.btn-primary:hover{
background-color: #a35a34;
}

.forgot{ margin-top:10px; text-align:left; }
.forgot a{ color:#333; text-decoration:underline; font-size:12.5px; }

.form-error{ color:#b00020; }
</style>
</head>

<body class="login-bg">


<div class="page">
<h1 class="brand">ESSENZA</h1>

<div class="login-card">
<form method="post" novalidate>
{% csrf_token %}

<label for="id_email">Correo electrónico</label>
{{ form.email }}

<label for="id_password">Contraseña</label>
{{ form.password }}

{% if form.non_field_errors %}
<p class="form-error">{{ form.non_field_errors.0 }}</p>
{% endif %}

<button type="submit" class="btn-primary">Iniciar sesión</button>

<p class="forgot">
<a href="{% url 'password_reset' %}">¿Has olvidado la contraseña?</a>
</p>
</form>
</div>
</div>

</body>
</html>
12 changes: 12 additions & 0 deletions essenza/user/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# user/forms.py
from django import forms

class LoginForm(forms.Form):
email = forms.CharField(
label="Correo electrónico o usuario",
widget=forms.TextInput(attrs={"placeholder": "Introduce tu correo o usuario"})
)
password = forms.CharField(
label="Contraseña",
widget=forms.PasswordInput(attrs={"placeholder": "Introduce tu contraseña"})
)
8 changes: 6 additions & 2 deletions essenza/user/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ class Usuario(AbstractUser):
foto = models.ImageField(upload_to='images/', null=True, blank=True)
role = models.CharField(max_length=10, choices=Role.choices, default=Role.USER)


email = models.EmailField(unique=True) # <-- aseguramos emails únicos

USERNAME_FIELD = 'email' # <-- se usará email para login
REQUIRED_FIELDS = ['username']

def __str__(self):
return self.username
return self.email
9 changes: 9 additions & 0 deletions essenza/user/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from django.contrib import admin
from django.urls import include, path
from django.http import HttpResponse
from user import views

urlpatterns = [
path('login/', views.LoginView.as_view(), name='login'),
]

35 changes: 33 additions & 2 deletions essenza/user/views.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,34 @@
from django.shortcuts import render
from django.shortcuts import render, redirect
from django.views import View
from django.contrib.auth import authenticate, login

from essenza.urls import home
from .forms import LoginForm


class LoginView(View):
form_class = LoginForm
template_name = 'user/login.html'


def get(self, request, *args, **kwargs):
if request.user.is_authenticated:
return redirect('home')
return render(request, self.template_name, {'form': self.form_class()})

def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
if form.is_valid():
email = form.cleaned_data["email"]
password = form.cleaned_data["password"]

user = authenticate(request, username=email, password=password)

if user is not None:
login(request, user)
return redirect('home')
else:
form.add_error(None, "Usuario o contraseña incorrectos")

return render(request, self.template_name, {'form': form})

# Create your views here.