diff --git a/core/__pycache__/forms.cpython-311.pyc b/core/__pycache__/forms.cpython-311.pyc new file mode 100644 index 0000000..d538a22 Binary files /dev/null and b/core/__pycache__/forms.cpython-311.pyc differ diff --git a/core/__pycache__/models.cpython-311.pyc b/core/__pycache__/models.cpython-311.pyc index 9aa598b..39bb88d 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 1f807fa..65aa3aa 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 6867ddf..9e99135 100644 Binary files a/core/__pycache__/views.cpython-311.pyc and b/core/__pycache__/views.cpython-311.pyc differ diff --git a/core/forms.py b/core/forms.py new file mode 100644 index 0000000..0fbbac6 --- /dev/null +++ b/core/forms.py @@ -0,0 +1,10 @@ +from django import forms +from django.contrib.auth.forms import UserCreationForm +from django.contrib.auth.models import User + +class SignUpForm(UserCreationForm): + email = forms.EmailField(max_length=254, help_text='Required. Inform a valid email address.') + + class Meta: + model = User + fields = ('username', 'email', 'password', 'password2') diff --git a/core/migrations/0001_initial.py b/core/migrations/0001_initial.py new file mode 100644 index 0000000..318c574 --- /dev/null +++ b/core/migrations/0001_initial.py @@ -0,0 +1,35 @@ +# Generated by Django 5.2.7 on 2025-12-08 02:20 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Club', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=100)), + ('description', models.TextField()), + ], + ), + migrations.CreateModel( + name='BookRecommendation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('book_title', models.CharField(max_length=200)), + ('author', models.CharField(max_length=100)), + ('reason', models.TextField()), + ('status', models.CharField(choices=[('pending', 'Pending'), ('approved', 'Approved'), ('rejected', 'Rejected')], default='pending', max_length=10)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('club', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.club')), + ], + ), + ] 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..2dff7cd 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..ac43acf 100644 --- a/core/models.py +++ b/core/models.py @@ -1,3 +1,24 @@ from django.db import models -# Create your models here. +class Club(models.Model): + name = models.CharField(max_length=100) + description = models.TextField() + + def __str__(self): + return self.name + +class BookRecommendation(models.Model): + STATUS_CHOICES = ( + ('pending', 'Pending'), + ('approved', 'Approved'), + ('rejected', 'Rejected'), + ) + club = models.ForeignKey(Club, on_delete=models.CASCADE) + book_title = models.CharField(max_length=200) + author = models.CharField(max_length=100) + reason = models.TextField() + status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='pending') + created_at = models.DateTimeField(auto_now_add=True) + + def __str__(self): + return f"{self.book_title} recommended for {self.club.name}" \ No newline at end of file diff --git a/core/templates/base.html b/core/templates/base.html index 1e7e5fb..c701a32 100644 --- a/core/templates/base.html +++ b/core/templates/base.html @@ -14,11 +14,40 @@ {% endif %} {% load static %} + {% block head %}{% endblock %} + + {% block content %}{% endblock %} diff --git a/core/templates/core/index.html b/core/templates/core/index.html index faec813..466ead4 100644 --- a/core/templates/core/index.html +++ b/core/templates/core/index.html @@ -1,145 +1,93 @@ -{% extends "base.html" %} + + + + + + Book Club - Social Reading App + {% load static %} + + + + + -{% block title %}{{ project_name }}{% endblock %} - -{% block head %} - - - - -{% endblock %} - -{% block content %} -
-
-

Analyzing your requirements and generating your app…

-
- Loading… +
+
+

Welcome to the Book Club

+

Create or join a book club, discuss your favorite books, and connect with fellow readers.

+ Join a Club +
-

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 + +
+
+
+
+

Create a Club

+

Start your own book club and invite your friends to join.

+
+
+
+
+

Choose Your Books

+

Select from a wide range of books or recommend new ones.

+
+
+
+
+

Join the Discussion

+

Share your thoughts, write reviews, and engage in discussions.

+
+
+
+
+ +
+
+

Recommend a Book

+ {% if submitted %} + + {% endif %} + {% if captcha_error %} + + {% endif %} +
+ {% csrf_token %} +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + + + +
+ +
+
+
+ + + + diff --git a/core/templates/core/login.html b/core/templates/core/login.html new file mode 100644 index 0000000..e2cc17e --- /dev/null +++ b/core/templates/core/login.html @@ -0,0 +1,20 @@ +{% extends 'base.html' %} + +{% block content %} +
+
+
+
+
+

Login

+
+ {% csrf_token %} + {{ form.as_p }} + +
+
+
+
+
+
+{% endblock %} diff --git a/core/templates/core/signup.html b/core/templates/core/signup.html new file mode 100644 index 0000000..a4e13cd --- /dev/null +++ b/core/templates/core/signup.html @@ -0,0 +1,20 @@ +{% extends 'base.html' %} + +{% block content %} +
+
+
+
+
+

Sign Up

+
+ {% csrf_token %} + {{ form.as_p }} + +
+
+
+
+
+
+{% endblock %} diff --git a/core/urls.py b/core/urls.py index 6299e3d..fcada4d 100644 --- a/core/urls.py +++ b/core/urls.py @@ -1,7 +1,10 @@ from django.urls import path - -from .views import home +from . import views +from .views import signup_view, login_view, logout_view urlpatterns = [ - path("", home, name="home"), -] + path('', views.index, name='index'), + path('signup/', signup_view, name='signup'), + path('login/', login_view, name='login'), + path('logout/', logout_view, name='logout'), +] \ No newline at end of file diff --git a/core/views.py b/core/views.py index c9aed12..a9eef7b 100644 --- a/core/views.py +++ b/core/views.py @@ -1,25 +1,71 @@ -import os -import platform +from django.shortcuts import render, redirect +from .models import Club, BookRecommendation +import random -from django import get_version as django_version -from django.shortcuts import render -from django.utils import timezone +def index(request): + if request.method == 'POST': + club_id = request.POST.get('club') + book_title = request.POST.get('book_title') + author = request.POST.get('author') + reason = request.POST.get('reason') + # Simple CAPTCHA + num1 = int(request.POST.get('num1')) + num2 = int(request.POST.get('num2')) + captcha = int(request.POST.get('captcha')) + + if captcha == num1 + num2: + club = Club.objects.get(id=club_id) + BookRecommendation.objects.create( + club=club, + book_title=book_title, + author=author, + reason=reason, + ) + return redirect('/?submitted=true') + else: + return redirect('/?captcha_error=true') -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() + clubs = Club.objects.all() + num1 = random.randint(1, 10) + num2 = random.randint(1, 10) + submitted = request.GET.get('submitted') + captcha_error = request.GET.get('captcha_error') + return render(request, 'core/index.html', { + 'clubs': clubs, + 'num1': num1, + 'num2': num2, + 'submitted': submitted, + 'captcha_error': captcha_error, + }) - 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) +from django.contrib.auth import login, logout +from django.contrib.auth.forms import AuthenticationForm +from .forms import SignUpForm + +def signup_view(request): + if request.method == 'POST': + form = SignUpForm(request.POST) + if form.is_valid(): + user = form.save() + login(request, user) + return redirect('/') + else: + form = SignUpForm() + return render(request, 'core/signup.html', {'form': form}) + +def login_view(request): + if request.method == 'POST': + form = AuthenticationForm(data=request.POST) + if form.is_valid(): + user = form.get_user() + login(request, user) + return redirect('/') + else: + form = AuthenticationForm() + return render(request, 'core/login.html', {'form': form}) + +def logout_view(request): + if request.method == 'POST': + logout(request) + return redirect('/') \ No newline at end of file diff --git a/static/css/custom.css b/static/css/custom.css index 925f6ed..8774ff6 100644 --- a/static/css/custom.css +++ b/static/css/custom.css @@ -1,4 +1,40 @@ -/* Custom styles for the application */ body { - font-family: system-ui, -apple-system, sans-serif; + font-family: 'Inter', sans-serif; + color: #333333; } + +.hero-section { + background: linear-gradient(45deg, #4F46E5, #9333EA); + color: white; + padding: 100px 0; + text-align: center; +} + +.hero-section h1 { + font-family: 'Poppins', sans-serif; + font-weight: 700; +} + +.feature-box { + padding: 30px; + border-radius: 10px; + background-color: #F5F5F5; + text-align: center; + margin-bottom: 20px; +} + +.recommendation-form { + padding: 40px; + border-radius: 10px; + background-color: #F5F5F5; +} + +.btn-primary { + background-color: #4F46E5; + border-color: #4F46E5; +} + +.btn-primary:hover { + background-color: #4338CA; + border-color: #4338CA; +} \ No newline at end of file diff --git a/staticfiles/css/custom.css b/staticfiles/css/custom.css index 108056f..8774ff6 100644 --- a/staticfiles/css/custom.css +++ b/staticfiles/css/custom.css @@ -1,21 +1,40 @@ - -:root { - --bg-color-start: #6a11cb; - --bg-color-end: #2575fc; - --text-color: #ffffff; - --card-bg-color: rgba(255, 255, 255, 0.01); - --card-border-color: rgba(255, 255, 255, 0.1); -} body { - margin: 0; font-family: 'Inter', sans-serif; - background: linear-gradient(45deg, var(--bg-color-start), var(--bg-color-end)); - color: var(--text-color); - display: flex; - justify-content: center; - align-items: center; - min-height: 100vh; - text-align: center; - overflow: hidden; - position: relative; + color: #333333; } + +.hero-section { + background: linear-gradient(45deg, #4F46E5, #9333EA); + color: white; + padding: 100px 0; + text-align: center; +} + +.hero-section h1 { + font-family: 'Poppins', sans-serif; + font-weight: 700; +} + +.feature-box { + padding: 30px; + border-radius: 10px; + background-color: #F5F5F5; + text-align: center; + margin-bottom: 20px; +} + +.recommendation-form { + padding: 40px; + border-radius: 10px; + background-color: #F5F5F5; +} + +.btn-primary { + background-color: #4F46E5; + border-color: #4F46E5; +} + +.btn-primary:hover { + background-color: #4338CA; + border-color: #4338CA; +} \ No newline at end of file