diff --git a/config/__pycache__/settings.cpython-311.pyc b/config/__pycache__/settings.cpython-311.pyc index 96bce55..6e8f76e 100644 Binary files a/config/__pycache__/settings.cpython-311.pyc and b/config/__pycache__/settings.cpython-311.pyc differ diff --git a/config/__pycache__/urls.cpython-311.pyc b/config/__pycache__/urls.cpython-311.pyc index 0b85e94..05127bd 100644 Binary files a/config/__pycache__/urls.cpython-311.pyc and b/config/__pycache__/urls.cpython-311.pyc differ diff --git a/config/settings.py b/config/settings.py index 291d043..b3db9aa 100644 --- a/config/settings.py +++ b/config/settings.py @@ -133,9 +133,9 @@ AUTH_PASSWORD_VALIDATORS = [ # Internationalization # https://docs.djangoproject.com/en/5.2/topics/i18n/ -LANGUAGE_CODE = 'en-us' +LANGUAGE_CODE = 'pt-br' -TIME_ZONE = 'UTC' +TIME_ZONE = 'America/Sao_Paulo' USE_I18N = True @@ -180,3 +180,5 @@ if EMAIL_USE_SSL: # https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' +MEDIA_URL = 'media/' +MEDIA_ROOT = BASE_DIR / 'media' diff --git a/config/urls.py b/config/urls.py index bcfc074..cccd18f 100644 --- a/config/urls.py +++ b/config/urls.py @@ -27,3 +27,4 @@ urlpatterns = [ if settings.DEBUG: urlpatterns += static("/assets/", document_root=settings.BASE_DIR / "assets") urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) + urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) \ No newline at end of file diff --git a/core/__pycache__/admin.cpython-311.pyc b/core/__pycache__/admin.cpython-311.pyc index a5ed392..f674c63 100644 Binary files a/core/__pycache__/admin.cpython-311.pyc and b/core/__pycache__/admin.cpython-311.pyc differ diff --git a/core/__pycache__/models.cpython-311.pyc b/core/__pycache__/models.cpython-311.pyc index e061640..7ade31e 100644 Binary files a/core/__pycache__/models.cpython-311.pyc and b/core/__pycache__/models.cpython-311.pyc differ diff --git a/core/__pycache__/urls.cpython-311.pyc b/core/__pycache__/urls.cpython-311.pyc index 5a69659..53aa62a 100644 Binary files a/core/__pycache__/urls.cpython-311.pyc and b/core/__pycache__/urls.cpython-311.pyc differ diff --git a/core/__pycache__/views.cpython-311.pyc b/core/__pycache__/views.cpython-311.pyc index 2a36fd6..d95d966 100644 Binary files a/core/__pycache__/views.cpython-311.pyc and b/core/__pycache__/views.cpython-311.pyc differ diff --git a/core/admin.py b/core/admin.py index 8c38f3f..037e470 100644 --- a/core/admin.py +++ b/core/admin.py @@ -1,3 +1,17 @@ from django.contrib import admin +from .models import MockupProject, MockupResult -# Register your models here. +class MockupResultInline(admin.TabularInline): + model = MockupResult + extra = 0 + +@admin.register(MockupProject) +class MockupProjectAdmin(admin.ModelAdmin): + list_display = ('title', 'user', 'status', 'created_at') + list_filter = ('status', 'gender', 'body_type') + search_fields = ('title', 'user__username') + inlines = [MockupResultInline] + +@admin.register(MockupResult) +class MockupResultAdmin(admin.ModelAdmin): + list_display = ('project', 'view_type', 'created_at') \ No newline at end of file diff --git a/core/migrations/0001_initial.py b/core/migrations/0001_initial.py new file mode 100644 index 0000000..2f490c0 --- /dev/null +++ b/core/migrations/0001_initial.py @@ -0,0 +1,53 @@ +# Generated by Django 5.2.7 on 2026-01-30 16:53 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='MockupProject', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=255, verbose_name='Título do Projeto')), + ('main_image', models.ImageField(upload_to='mockups/uploads/', verbose_name='Imagem Principal')), + ('complementary_image_1', models.ImageField(blank=True, null=True, upload_to='mockups/uploads/')), + ('complementary_image_2', models.ImageField(blank=True, null=True, upload_to='mockups/uploads/')), + ('gender', models.CharField(choices=[('M', 'Masculino'), ('F', 'Feminino'), ('N', 'Não-binário')], default='F', max_length=1, verbose_name='Gênero')), + ('skin_tone', models.CharField(choices=[('light', 'Claro'), ('medium', 'Médio'), ('dark', 'Escuro')], default='medium', max_length=20, verbose_name='Tom de Pele')), + ('age', models.IntegerField(default=25, verbose_name='Idade')), + ('body_type', models.CharField(choices=[('plus', 'Plus-size'), ('slim', 'Magro'), ('athletic', 'Atlético'), ('muscular', 'Musculoso')], default='athletic', max_length=20, verbose_name='Tipo de Corpo')), + ('format', models.CharField(choices=[('9:16', '9:16 (Vertical)'), ('16:9', '16:9 (Horizontal)')], default='9:16', max_length=5, verbose_name='Formato')), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('status', models.CharField(default='pending', max_length=20)), + ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name': 'Projeto de Mockup', + 'verbose_name_plural': 'Projetos de Mockup', + }, + ), + migrations.CreateModel( + name='MockupResult', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('image', models.ImageField(upload_to='mockups/results/')), + ('view_type', models.CharField(max_length=10)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='results', to='core.mockupproject')), + ], + options={ + 'verbose_name': 'Resultado do Mockup', + 'verbose_name_plural': 'Resultados dos Mockups', + }, + ), + ] diff --git a/core/migrations/__pycache__/0001_initial.cpython-311.pyc b/core/migrations/__pycache__/0001_initial.cpython-311.pyc new file mode 100644 index 0000000..792a6b0 Binary files /dev/null and b/core/migrations/__pycache__/0001_initial.cpython-311.pyc differ diff --git a/core/models.py b/core/models.py index 71a8362..ffd9ed5 100644 --- a/core/models.py +++ b/core/models.py @@ -1,3 +1,56 @@ from django.db import models +from django.contrib.auth.models import User -# Create your models here. +class MockupProject(models.Model): + GENDER_CHOICES = [ + ('M', 'Masculino'), + ('F', 'Feminino'), + ('N', 'Não-binário'), + ] + SKIN_TONE_CHOICES = [ + ('light', 'Claro'), + ('medium', 'Médio'), + ('dark', 'Escuro'), + ] + BODY_TYPE_CHOICES = [ + ('plus', 'Plus-size'), + ('slim', 'Magro'), + ('athletic', 'Atlético'), + ('muscular', 'Musculoso'), + ] + FORMAT_CHOICES = [ + ('9:16', '9:16 (Vertical)'), + ('16:9', '16:9 (Horizontal)'), + ] + + user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True) + title = models.CharField(max_length=255, verbose_name="Título do Projeto") + main_image = models.ImageField(upload_to='mockups/uploads/', verbose_name="Imagem Principal") + complementary_image_1 = models.ImageField(upload_to='mockups/uploads/', null=True, blank=True) + complementary_image_2 = models.ImageField(upload_to='mockups/uploads/', null=True, blank=True) + + gender = models.CharField(max_length=1, choices=GENDER_CHOICES, default='F', verbose_name="Gênero") + skin_tone = models.CharField(max_length=20, choices=SKIN_TONE_CHOICES, default='medium', verbose_name="Tom de Pele") + age = models.IntegerField(default=25, verbose_name="Idade") + body_type = models.CharField(max_length=20, choices=BODY_TYPE_CHOICES, default='athletic', verbose_name="Tipo de Corpo") + format = models.CharField(max_length=5, choices=FORMAT_CHOICES, default='9:16', verbose_name="Formato") + + created_at = models.DateTimeField(auto_now_add=True) + status = models.CharField(max_length=20, default='pending') + + class Meta: + verbose_name = "Projeto de Mockup" + verbose_name_plural = "Projetos de Mockup" + + def __str__(self): + return self.title + +class MockupResult(models.Model): + project = models.ForeignKey(MockupProject, on_delete=models.CASCADE, related_name='results') + image = models.ImageField(upload_to='mockups/results/') + view_type = models.CharField(max_length=10) # front, side, back + created_at = models.DateTimeField(auto_now_add=True) + + class Meta: + verbose_name = "Resultado do Mockup" + verbose_name_plural = "Resultados dos Mockups" \ No newline at end of file diff --git a/core/templates/base.html b/core/templates/base.html index 1e7e5fb..197f43d 100644 --- a/core/templates/base.html +++ b/core/templates/base.html @@ -1,25 +1,122 @@ - + - {% block title %}Knowledge Base{% endblock %} - {% if project_description %} - - - - {% endif %} - {% if project_image_url %} - - - {% endif %} + + {% block title %}FashionMock AI{% endblock %} + + + + + + + + + {% load static %} + + {% block head %}{% endblock %} - {% block content %}{% endblock %} + + +
+ {% block content %}{% endblock %} +
+ + + + - + \ No newline at end of file diff --git a/core/templates/core/create_mockup.html b/core/templates/core/create_mockup.html new file mode 100644 index 0000000..da3c7a9 --- /dev/null +++ b/core/templates/core/create_mockup.html @@ -0,0 +1,132 @@ +{% extends 'base.html' %} +{% load static %} + +{% block content %} +
+
+
+
+
+

Novo Projeto de Mockup

+ +
+ {% csrf_token %} + +
+ +
+

1. Upload das Fotos

+
+ + +
+ +
+ +
+ +
+ + + + +

Clique para selecionar foto

+
+
+
+ +
+
+ + +
+
+ + +
+
+
+ + +
+

2. Customização do Modelo

+ +
+ + +
+ +
+ +
+ + + + + + + + +
+
+ +
+ + +
+ +
+ + +
+ +
+ +
+ + + + + +
+
+ + +

A geração leva aprox. 1-2 minutos.

+
+
+
+
+
+
+
+
+ + +{% endblock %} diff --git a/core/templates/core/dashboard.html b/core/templates/core/dashboard.html new file mode 100644 index 0000000..70d721b --- /dev/null +++ b/core/templates/core/dashboard.html @@ -0,0 +1,48 @@ +{% extends 'base.html' %} + +{% block content %} +
+
+
+

Meus Mockups

+ Novo Projeto +
+ + {% if projects %} +
+ {% for project in projects %} +
+
+
+ {{ project.title }} +
+ + {{ project.status|capfirst }} + +
+
+
+
{{ project.title }}
+

{{ project.created_at|date:"d/m/Y H:i" }}

+ Ver Detalhes +
+
+
+ {% endfor %} +
+ {% else %} +
+
+ + + + +

Nenhum projeto ainda

+

Comece enviando sua primeira peça de roupa.

+ CRIAR MEU PRIMEIRO MOCKUP +
+
+ {% endif %} +
+
+{% endblock %} diff --git a/core/templates/core/index.html b/core/templates/core/index.html index faec813..6edac39 100644 --- a/core/templates/core/index.html +++ b/core/templates/core/index.html @@ -1,145 +1,88 @@ -{% extends "base.html" %} - -{% block title %}{{ project_name }}{% endblock %} - -{% block head %} - - - - -{% endblock %} +{% extends 'base.html' %} +{% load static %} {% block content %} -
-
-

Analyzing your requirements and generating your app…

-
- Loading… + +
+
+
+
+ SaaS de Moda AI +

Transforme suas peças em mockups reais em minutos.

+

Crie fotos profissionais para seu catálogo e redes sociais sem precisar de modelos ou estúdios caros. Tecnologia AI de alta fidelidade para o mercado brasileiro.

+ +
+
+
+
+ Fashion Mockup Example +
+

Gerado por AI

+ Modelo: Feminino, 25 anos, Atlético +
+
+
+
-

AppWizzy AI is collecting your requirements and applying the first changes.

-

This page will refresh automatically as the plan is implemented.

-

- Runtime: Django {{ django_version }} · Python {{ python_version }} - — UTC {{ current_time|date:"Y-m-d H:i:s" }} -

-
- -{% endblock %} \ No newline at end of file + + + +
+
+
+

Como Funciona

+

Simples, rápido e ultra-realista.

+
+
+
+
+
+ + + + +
+

1. Upload

+

Suba as fotos das suas peças reais. Sem truques, apenas a sua criação.

+
+
+
+
+
+ + + +
+

2. Customize

+

Escolha o modelo, idade, tom de pele e biotipo que melhor representa sua marca.

+
+
+
+
+
+ + + + +
+

3. Gere e Baixe

+

Em minutos, receba 3 mockups (frente, lado e costas) prontos para uso em HD.

+
+
+
+
+
+ + +
+
+

Pronto para elevar sua marca?

+

Junte-se a centenas de marcas brasileiras que já usam FashionMock AI.

+ CRIAR MEU PRIMEIRO MOCKUP +
+
+{% endblock %} diff --git a/core/templates/core/login.html b/core/templates/core/login.html new file mode 100644 index 0000000..9a38600 --- /dev/null +++ b/core/templates/core/login.html @@ -0,0 +1,45 @@ +{% extends 'base.html' %} + +{% block content %} +
+
+
+
+
+
+

Bem-vindo

+

Entre na sua conta FashionMock AI

+
+ +
+ {% csrf_token %} +
+ + +
+
+ + +
+ + + +
+ Esqueceu a senha? +
+

Ainda não tem conta? Crie uma agora

+
+
+ +
+ +
+
+
+
+
+
+{% endblock %} diff --git a/core/templates/core/project_detail.html b/core/templates/core/project_detail.html new file mode 100644 index 0000000..f8f9a54 --- /dev/null +++ b/core/templates/core/project_detail.html @@ -0,0 +1,85 @@ +{% extends 'base.html' %} + +{% block content %} +
+
+ + +
+
+
+

Detalhes do Projeto

+ Original + +
+ Status + {% if project.status == 'pending' %}Aguardando Processamento{% else %}{{ project.status|capfirst }}{% endif %} +
+ +
+ Modelo +

+ Gênero: {{ project.get_gender_display }}
+ Tom de Pele: {{ project.get_skin_tone_display }}
+ Idade: {{ project.age }} anos
+ Biotipo: {{ project.get_body_type_display }} +

+
+ +
+ Formato + {{ project.format }} +
+
+
+ +
+
+

Resultados Gerados

+ + {% if project.results.all %} +
+ {% for result in project.results.all %} +
+
+ {{ result.view_type }} +
+ {{ result.view_type|capfirst }} + Baixar +
+
+
+ {% endfor %} +
+ {% else %} +
+
+ Processando... +
+

Sua mágica está sendo preparada...

+

Nossa AI está vestindo os modelos e ajustando a iluminação. Isso levará cerca de 60 segundos.

+
+
+
+
+ {% endif %} +
+
+
+
+
+ +{% if project.status == 'pending' %} + +{% endif %} +{% endblock %} diff --git a/core/urls.py b/core/urls.py index 6299e3d..41eb32d 100644 --- a/core/urls.py +++ b/core/urls.py @@ -1,7 +1,14 @@ from django.urls import path - -from .views import home +from . import views +from django.contrib.auth import views as auth_views urlpatterns = [ - path("", home, name="home"), -] + path("", views.home, name="index"), + path("dashboard/", views.dashboard, name="dashboard"), + path("criar/", views.create_mockup, name="create_mockup"), + path("projeto//", views.project_detail, name="project_detail"), + + # Auth + path("login/", auth_views.LoginView.as_view(template_name="core/login.html"), name="login"), + path("logout/", auth_views.LogoutView.as_view(next_page="index"), name="logout"), +] \ No newline at end of file diff --git a/core/views.py b/core/views.py index c9aed12..adc8a3b 100644 --- a/core/views.py +++ b/core/views.py @@ -1,25 +1,37 @@ import os -import platform - -from django import get_version as django_version -from django.shortcuts import render -from django.utils import timezone - +from django.shortcuts import render, redirect +from django.contrib.auth.decorators import login_required +from .models import MockupProject, MockupResult def home(request): - """Render the landing screen with loader and environment details.""" - host_name = request.get_host().lower() - agent_brand = "AppWizzy" if host_name == "appwizzy.com" else "Flatlogic" - now = timezone.now() + """Polished landing page for FashionMock AI.""" + return render(request, "core/index.html") - context = { - "project_name": "New Style", - "agent_brand": agent_brand, - "django_version": django_version(), - "python_version": platform.python_version(), - "current_time": now, - "host_name": host_name, - "project_description": os.getenv("PROJECT_DESCRIPTION", ""), - "project_image_url": os.getenv("PROJECT_IMAGE_URL", ""), - } - return render(request, "core/index.html", context) +@login_required +def dashboard(request): + """User dashboard showing project history.""" + projects = MockupProject.objects.filter(user=request.user).order_by('-created_at') + return render(request, "core/dashboard.html", {"projects": projects}) + +@login_required +def create_mockup(request): + """Workflow to create a new fashion mockup.""" + if request.method == "POST": + project = MockupProject.objects.create( + user=request.user, + title=request.POST.get("title", "Novo Projeto"), + main_image=request.FILES.get("main_image"), + gender=request.POST.get("gender", "F"), + skin_tone=request.POST.get("skin_tone", "medium"), + age=request.POST.get("age", 25), + body_type=request.POST.get("body_type", "athletic"), + format=request.POST.get("format", "9:16") + ) + return redirect('dashboard') + + return render(request, "core/create_mockup.html") + +def project_detail(request, pk): + """View details and results of a mockup project.""" + project = MockupProject.objects.get(pk=pk) + return render(request, "core/project_detail.html", {"project": project}) \ No newline at end of file