diff --git a/config/__pycache__/__init__.cpython-311.pyc b/config/__pycache__/__init__.cpython-311.pyc index 423a636..77844aa 100644 Binary files a/config/__pycache__/__init__.cpython-311.pyc and b/config/__pycache__/__init__.cpython-311.pyc differ diff --git a/config/__pycache__/settings.cpython-311.pyc b/config/__pycache__/settings.cpython-311.pyc index 96bce55..f3681b4 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..9ce5ebf 100644 Binary files a/config/__pycache__/urls.cpython-311.pyc and b/config/__pycache__/urls.cpython-311.pyc differ diff --git a/config/__pycache__/wsgi.cpython-311.pyc b/config/__pycache__/wsgi.cpython-311.pyc index 9c49e09..bd17a1a 100644 Binary files a/config/__pycache__/wsgi.cpython-311.pyc and b/config/__pycache__/wsgi.cpython-311.pyc differ diff --git a/config/urls.py b/config/urls.py index bcfc074..2001e5f 100644 --- a/config/urls.py +++ b/config/urls.py @@ -1,19 +1,3 @@ -""" -URL configuration for config project. - -The `urlpatterns` list routes URLs to views. For more information please see: - https://docs.djangoproject.com/en/5.2/topics/http/urls/ -Examples: -Function views - 1. Add an import: from my_app import views - 2. Add a URL to urlpatterns: path('', views.home, name='home') -Class-based views - 1. Add an import: from other_app.views import Home - 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') -Including another URLconf - 1. Import the include() function: from django.urls import include, path - 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) -""" from django.contrib import admin from django.urls import include, path from django.conf import settings @@ -21,9 +5,10 @@ from django.conf.urls.static import static urlpatterns = [ path("admin/", admin.site.urls), + path("accounts/", include("django.contrib.auth.urls")), path("", include("core.urls")), ] 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.STATIC_URL, document_root=settings.STATIC_ROOT) \ No newline at end of file diff --git a/core/__pycache__/__init__.cpython-311.pyc b/core/__pycache__/__init__.cpython-311.pyc index 74b1112..7a1cd84 100644 Binary files a/core/__pycache__/__init__.cpython-311.pyc and b/core/__pycache__/__init__.cpython-311.pyc differ diff --git a/core/__pycache__/admin.cpython-311.pyc b/core/__pycache__/admin.cpython-311.pyc index a5ed392..42e9f65 100644 Binary files a/core/__pycache__/admin.cpython-311.pyc and b/core/__pycache__/admin.cpython-311.pyc differ diff --git a/core/__pycache__/apps.cpython-311.pyc b/core/__pycache__/apps.cpython-311.pyc index 6f131d4..f77d222 100644 Binary files a/core/__pycache__/apps.cpython-311.pyc and b/core/__pycache__/apps.cpython-311.pyc differ diff --git a/core/__pycache__/context_processors.cpython-311.pyc b/core/__pycache__/context_processors.cpython-311.pyc index 75bf223..7daedb5 100644 Binary files a/core/__pycache__/context_processors.cpython-311.pyc and b/core/__pycache__/context_processors.cpython-311.pyc differ diff --git a/core/__pycache__/models.cpython-311.pyc b/core/__pycache__/models.cpython-311.pyc index e061640..42c46bb 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..b816ebb 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..8f7d76d 100644 Binary files a/core/__pycache__/views.cpython-311.pyc and b/core/__pycache__/views.cpython-311.pyc differ diff --git a/core/migrations/0001_initial.py b/core/migrations/0001_initial.py new file mode 100644 index 0000000..4e59bee --- /dev/null +++ b/core/migrations/0001_initial.py @@ -0,0 +1,55 @@ +# Generated by Django 5.2.7 on 2026-02-23 14:00 + +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='Instructor', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255)), + ('title', models.CharField(help_text='e.g. Professor of Computer Science', max_length=255)), + ('bio', models.TextField()), + ('expertise', models.CharField(max_length=255)), + ('photo_url', models.URLField(blank=True, null=True)), + ], + ), + migrations.CreateModel( + name='Course', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=255)), + ('slug', models.SlugField(unique=True)), + ('description', models.TextField()), + ('price', models.DecimalField(decimal_places=2, max_digits=10)), + ('duration', models.CharField(help_text='e.g. 10 weeks', max_length=100)), + ('level', models.CharField(choices=[('Beginner', 'Beginner'), ('Intermediate', 'Intermediate'), ('Advanced', 'Advanced')], max_length=50)), + ('image_url', models.URLField(blank=True, null=True)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('instructor', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='courses', to='core.instructor')), + ], + ), + migrations.CreateModel( + name='WishlistItem', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('added_at', models.DateTimeField(auto_now_add=True)), + ('course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.course')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='wishlist', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'unique_together': {('user', 'course')}, + }, + ), + ] 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..72c5699 Binary files /dev/null and b/core/migrations/__pycache__/0001_initial.cpython-311.pyc differ diff --git a/core/migrations/__pycache__/__init__.cpython-311.pyc b/core/migrations/__pycache__/__init__.cpython-311.pyc index 9c833c8..1497804 100644 Binary files a/core/migrations/__pycache__/__init__.cpython-311.pyc and b/core/migrations/__pycache__/__init__.cpython-311.pyc differ diff --git a/core/models.py b/core/models.py index 71a8362..d4a95dd 100644 --- a/core/models.py +++ b/core/models.py @@ -1,3 +1,42 @@ from django.db import models +from django.contrib.auth.models import User -# Create your models here. +class Instructor(models.Model): + name = models.CharField(max_length=255) + title = models.CharField(max_length=255, help_text="e.g. Professor of Computer Science") + bio = models.TextField() + expertise = models.CharField(max_length=255) + photo_url = models.URLField(blank=True, null=True) + + def __str__(self): + return self.name + +class Course(models.Model): + LEVEL_CHOICES = [ + ('Beginner', 'Beginner'), + ('Intermediate', 'Intermediate'), + ('Advanced', 'Advanced'), + ] + title = models.CharField(max_length=255) + slug = models.SlugField(unique=True) + description = models.TextField() + instructor = models.ForeignKey(Instructor, on_delete=models.CASCADE, related_name='courses') + price = models.DecimalField(max_digits=10, decimal_places=2) + duration = models.CharField(max_length=100, help_text="e.g. 10 weeks") + level = models.CharField(max_length=50, choices=LEVEL_CHOICES) + image_url = models.URLField(blank=True, null=True) + created_at = models.DateTimeField(auto_now_add=True) + + def __str__(self): + return self.title + +class WishlistItem(models.Model): + user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='wishlist') + course = models.ForeignKey(Course, on_delete=models.CASCADE) + added_at = models.DateTimeField(auto_now_add=True) + + class Meta: + unique_together = ('user', 'course') + + def __str__(self): + return f"{self.user.username} - {self.course.title}" diff --git a/core/templates/base.html b/core/templates/base.html index 1e7e5fb..1560954 100644 --- a/core/templates/base.html +++ b/core/templates/base.html @@ -1,25 +1,117 @@ - - - {% block title %}Knowledge Base{% endblock %} - {% if project_description %} - - - - {% endif %} - {% if project_image_url %} - - - {% endif %} - {% load static %} - - {% block head %}{% endblock %} + + + {% block title %}Academic Excellence{% endblock %} + + + {% load static %} + + + {% block extra_css %}{% endblock %} - - {% block content %}{% endblock %} - + - +
+ {% block content %}{% endblock %} +
+ + + + + {% block extra_js %}{% endblock %} + + \ No newline at end of file diff --git a/core/templates/core/checkout_placeholder.html b/core/templates/core/checkout_placeholder.html new file mode 100644 index 0000000..cefa4a6 --- /dev/null +++ b/core/templates/core/checkout_placeholder.html @@ -0,0 +1,45 @@ +{% extends 'base.html' %} + +{% block title %}Checkout - {{ course.title }}{% endblock %} + +{% block content %} +
+
+
+
+
+ + + +
+

Complete Your Enrollment

+

You're one step away from joining {{ course.title }}.

+ +
+
+ Course Fee + ${{ course.price }} +
+
+ Discount + -$0.00 +
+
+
+ Total + ${{ course.price }} +
+
+ +
+ + +
+ +

This is a placeholder for the final checkout flow.

+ Back to Course +
+
+
+
+{% endblock %} diff --git a/core/templates/core/course_detail.html b/core/templates/core/course_detail.html new file mode 100644 index 0000000..29e524a --- /dev/null +++ b/core/templates/core/course_detail.html @@ -0,0 +1,111 @@ +{% extends 'base.html' %} + +{% block title %}{{ course.title }} - Academic Excellence{% endblock %} + +{% block content %} +
+
+ +
+
+ {{ course.level }} +

{{ course.title }}

+

{{ course.description }}

+
+
+ {% if course.instructor.photo_url %} + + {% endif %} +
+ Instructor + {{ course.instructor.name }} +
+
+
+ Duration + {{ course.duration }} +
+
+ Price + ${{ course.price }} +
+
+
+
+
+ {% if course.image_url %} + {{ course.title }} + {% endif %} +
+

${{ course.price }}

+ +

30-Day Money-Back Guarantee

+
+
+
+
+
+
+ +
+
+
+

Course Content

+
+
+

+ +

+
+
+ Detailed overview of core concepts and initial setup. +
+
+
+
+

+ +

+
+
+ Deep dive into complex topics and real-world applications. +
+
+
+
+ +
+

About the Instructor

+
+ {% if course.instructor.photo_url %} + + {% endif %} +
+

{{ course.instructor.name }}

+

{{ course.instructor.title }}

+

{{ course.instructor.bio }}

+
+
+
+
+
+
+{% endblock %} diff --git a/core/templates/core/index.html b/core/templates/core/index.html index faec813..b816327 100644 --- a/core/templates/core/index.html +++ b/core/templates/core/index.html @@ -1,145 +1,86 @@ -{% 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… +
+
+
+
+

Elevate Your Future with Expert Guidance

+

Discover a curated catalog of world-class courses taught by leading academics and industry professionals.

+ +
+
+
+
+
+
+
+
+
+
+
+
-

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

Our Courses

+
+
+
+ + + +
+
+
+ +
+ {% for course in courses %} +
+
+ {% if course.image_url %} + {{ course.title }} + {% else %} +
+ No Image Available +
+ {% endif %} +
+
+ {{ course.level }} + ${{ course.price }} +
+
{{ course.title }}
+

{{ course.description|truncatewords:20 }}

+
+ {% if course.instructor.photo_url %} + + {% endif %} + By {{ course.instructor.name }} +
+
+ +
+
+ {% empty %} +
+

No courses found matching your criteria.

+
+ {% endfor %} +
+
+{% endblock %} diff --git a/core/templates/core/instructor_detail.html b/core/templates/core/instructor_detail.html new file mode 100644 index 0000000..260290b --- /dev/null +++ b/core/templates/core/instructor_detail.html @@ -0,0 +1,45 @@ +{% extends 'base.html' %} + +{% block title %}{{ instructor.name }} - Academic Excellence{% endblock %} + +{% block content %} +
+
+
+
+ {% if instructor.photo_url %} + + {% endif %} +

{{ instructor.name }}

+

{{ instructor.title }}

+
+ {{ instructor.expertise }} +
+
+
+
+

Biography

+
+ {{ instructor.bio|linebreaks }} +
+ +

Courses by {{ instructor.name }}

+
+ {% for course in instructor.courses.all %} +
+
+
+ {{ course.level }} +
{{ course.title }}
+ View Course → +
+
+
+ {% empty %} +

No courses listed yet.

+ {% endfor %} +
+
+
+
+{% endblock %} diff --git a/core/templates/core/wishlist.html b/core/templates/core/wishlist.html new file mode 100644 index 0000000..18cd4ba --- /dev/null +++ b/core/templates/core/wishlist.html @@ -0,0 +1,41 @@ +{% extends 'base.html' %} + +{% block title %}My Wishlist - Academic Excellence{% endblock %} + +{% block content %} +
+
+

My Wishlist

+

Courses you've saved for later.

+
+ +
+ {% for item in items %} +
+
+ {% if item.course.image_url %} + {{ item.course.title }} + {% endif %} +
+
{{ item.course.title }}
+

By {{ item.course.instructor.name }}

+
+ View + Remove +
+
+
+
+ {% empty %} +
+
+ +
+

Your wishlist is empty

+

Start exploring our catalog to find your next course.

+ Explore Courses +
+ {% endfor %} +
+
+{% endblock %} diff --git a/core/templates/registration/login.html b/core/templates/registration/login.html new file mode 100644 index 0000000..e57f4a8 --- /dev/null +++ b/core/templates/registration/login.html @@ -0,0 +1,32 @@ +{% extends 'base.html' %} + +{% block title %}Login - Academic Excellence{% endblock %} + +{% block content %} +
+
+
+
+

Welcome Back

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

+ Don't have an account? Sign Up +

+
+
+
+
+{% endblock %} diff --git a/core/templates/registration/signup.html b/core/templates/registration/signup.html new file mode 100644 index 0000000..afe5c3f --- /dev/null +++ b/core/templates/registration/signup.html @@ -0,0 +1,34 @@ +{% extends 'base.html' %} + +{% block title %}Sign Up - Academic Excellence{% endblock %} + +{% block content %} +
+
+
+
+

Create Account

+
+ {% csrf_token %} + {% for field in form %} +
+ + {{ field.errors }} + + {% if field.help_text %} +
{{ field.help_text|safe }}
+ {% endif %} +
+ {% endfor %} +
+ +
+
+

+ Already have an account? Login +

+
+
+
+
+{% endblock %} diff --git a/core/urls.py b/core/urls.py index 6299e3d..606b0c1 100644 --- a/core/urls.py +++ b/core/urls.py @@ -1,7 +1,12 @@ from django.urls import path - -from .views import home +from . import views urlpatterns = [ - path("", home, name="home"), + path('', views.course_list, name='home'), + path('course//', views.course_detail, name='course_detail'), + path('instructor//', views.instructor_detail, name='instructor_detail'), + path('wishlist/', views.wishlist, name='wishlist'), + path('wishlist/toggle//', views.toggle_wishlist, name='toggle_wishlist'), + path('checkout//', views.checkout_placeholder, name='checkout_placeholder'), + path('signup/', views.signup, name='signup'), ] diff --git a/core/views.py b/core/views.py index c9aed12..afd7891 100644 --- a/core/views.py +++ b/core/views.py @@ -1,25 +1,74 @@ -import os -import platform - -from django import get_version as django_version -from django.shortcuts import render -from django.utils import timezone - - -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() +from django.shortcuts import render, get_object_or_404, redirect +from django.contrib.auth.decorators import login_required +from django.db.models import Q +from django.contrib.auth.forms import UserCreationForm +from django.contrib.auth import login +from .models import Course, Instructor, WishlistItem +def course_list(request): + query = request.GET.get('q', '') + level = request.GET.get('level', '') + + courses = Course.objects.all() + + if query: + courses = courses.filter( + Q(title__icontains=query) | Q(description__icontains=query) + ) + + if level: + courses = courses.filter(level=level) + 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", ""), + 'courses': courses, + 'query': query, + 'level': level, + 'levels': ['Beginner', 'Intermediate', 'Advanced'] } - return render(request, "core/index.html", context) + return render(request, 'core/index.html', context) + +def course_detail(request, slug): + course = get_object_or_404(Course, slug=slug) + is_in_wishlist = False + if request.user.is_authenticated: + is_in_wishlist = WishlistItem.objects.filter(user=request.user, course=course).exists() + + context = { + 'course': course, + 'is_in_wishlist': is_in_wishlist + } + return render(request, 'core/course_detail.html', context) + +def instructor_detail(request, pk): + instructor = get_object_or_404(Instructor, pk=pk) + return render(request, 'core/instructor_detail.html', {'instructor': instructor}) + +@login_required +def wishlist(request): + items = WishlistItem.objects.filter(user=request.user) + return render(request, 'core/wishlist.html', {'items': items}) + +@login_required +def toggle_wishlist(request, course_id): + course = get_object_or_404(Course, id=course_id) + wishlist_item, created = WishlistItem.objects.get_or_create(user=request.user, course=course) + + if not created: + wishlist_item.delete() + + return redirect(request.META.get('HTTP_REFERER', 'home')) + +def checkout_placeholder(request, course_id): + course = get_object_or_404(Course, id=course_id) + return render(request, 'core/checkout_placeholder.html', {'course': course}) + +def signup(request): + if request.method == 'POST': + form = UserCreationForm(request.POST) + if form.is_valid(): + user = form.save() + login(request, user) + return redirect('home') + else: + form = UserCreationForm() + return render(request, 'registration/signup.html', {'form': form})