diff --git a/config/__pycache__/settings.cpython-311.pyc b/config/__pycache__/settings.cpython-311.pyc index 881731c..80c1dd3 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 42d995d..4b360a6 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..6ed069d 100644 --- a/config/settings.py +++ b/config/settings.py @@ -180,3 +180,7 @@ if EMAIL_USE_SSL: # https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' + +# Media files (Uploads) +MEDIA_URL = 'media/' +MEDIA_ROOT = BASE_DIR / 'media' \ No newline at end of file diff --git a/config/urls.py b/config/urls.py index bcfc074..4d15824 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 @@ -25,5 +9,5 @@ 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) + urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) \ No newline at end of file diff --git a/core/__pycache__/admin.cpython-311.pyc b/core/__pycache__/admin.cpython-311.pyc index 2964e11..7847a78 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 18a063c..4fac4a6 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 ebb8c6e..2678d58 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 8d204fa..420bd20 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..a8ffa32 100644 --- a/core/admin.py +++ b/core/admin.py @@ -1,3 +1,53 @@ from django.contrib import admin +from .models import Category, Book, Order +from django.utils.html import format_html -# Register your models here. +@admin.register(Category) +class CategoryAdmin(admin.ModelAdmin): + list_display = ('name', 'slug', 'book_count', 'display_image') + prepopulated_fields = {'slug': ('name',)} + + def book_count(self, obj): + return obj.books.count() + book_count.short_description = 'Books' + + def display_image(self, obj): + if obj.image: + return format_html('', obj.image.url) + return "-" + display_image.short_description = 'Image' + +@admin.register(Book) +class BookAdmin(admin.ModelAdmin): + list_display = ('title', 'category', 'price', 'is_featured', 'display_cover', 'created_at') + list_filter = ('category', 'is_featured', 'created_at') + list_editable = ('is_featured',) + search_fields = ('title', 'description') + prepopulated_fields = {'slug': ('title',)} + + def display_cover(self, obj): + if obj.cover_image: + return format_html('', obj.cover_image.url) + return "-" + display_cover.short_description = 'Cover' + +@admin.register(Order) +class OrderAdmin(admin.ModelAdmin): + list_display = ('book', 'user_email', 'transaction_id', 'status', 'display_screenshot', 'created_at') + list_filter = ('status', 'created_at') + search_fields = ('user_email', 'transaction_id') + actions = ['approve_orders', 'reject_orders'] + + def approve_orders(self, request, queryset): + queryset.update(status='approved') + approve_orders.short_description = "✅ Mark as Approved" + + def reject_orders(self, request, queryset): + queryset.update(status='rejected') + reject_orders.short_description = "❌ Mark as Rejected" + + def display_screenshot(self, obj): + if obj.payment_screenshot: + return format_html('', obj.payment_screenshot.url, obj.payment_screenshot.url) + return "No Proof" + display_screenshot.short_description = 'Payment Proof' \ 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..57dd77c --- /dev/null +++ b/core/migrations/0001_initial.py @@ -0,0 +1,52 @@ +# Generated by Django 5.2.7 on 2026-02-19 18:13 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Category', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=100)), + ('slug', models.SlugField(blank=True, unique=True)), + ], + options={ + 'verbose_name_plural': 'Categories', + }, + ), + migrations.CreateModel( + name='Book', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=255)), + ('description', models.TextField()), + ('price', models.DecimalField(decimal_places=2, max_digits=10)), + ('pdf_file', models.FileField(upload_to='books/pdfs/')), + ('cover_image', models.ImageField(blank=True, null=True, upload_to='books/covers/')), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('slug', models.SlugField(blank=True, unique=True)), + ('category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='books', to='core.category')), + ], + ), + migrations.CreateModel( + name='Order', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('user_email', models.EmailField(max_length=254)), + ('transaction_id', models.CharField(help_text='Enter your EVC/Zaad/Sahal transaction ID or reference', max_length=100)), + ('payment_screenshot', models.ImageField(blank=True, null=True, upload_to='payments/')), + ('status', models.CharField(choices=[('pending', 'Pending'), ('approved', 'Approved'), ('rejected', 'Rejected')], default='pending', max_length=20)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('book', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.book')), + ], + ), + ] diff --git a/core/migrations/0002_book_is_featured_category_image.py b/core/migrations/0002_book_is_featured_category_image.py new file mode 100644 index 0000000..cf077db --- /dev/null +++ b/core/migrations/0002_book_is_featured_category_image.py @@ -0,0 +1,23 @@ +# Generated by Django 5.2.7 on 2026-02-19 18:45 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='book', + name='is_featured', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='category', + name='image', + field=models.ImageField(blank=True, null=True, upload_to='categories/'), + ), + ] 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..c470a15 Binary files /dev/null and b/core/migrations/__pycache__/0001_initial.cpython-311.pyc differ diff --git a/core/migrations/__pycache__/0002_book_is_featured_category_image.cpython-311.pyc b/core/migrations/__pycache__/0002_book_is_featured_category_image.cpython-311.pyc new file mode 100644 index 0000000..49b4dbf Binary files /dev/null and b/core/migrations/__pycache__/0002_book_is_featured_category_image.cpython-311.pyc differ diff --git a/core/models.py b/core/models.py index 71a8362..9fb9ac2 100644 --- a/core/models.py +++ b/core/models.py @@ -1,3 +1,53 @@ from django.db import models +from django.utils.text import slugify -# Create your models here. +class Category(models.Model): + name = models.CharField(max_length=100) + slug = models.SlugField(unique=True, blank=True) + image = models.ImageField(upload_to='categories/', blank=True, null=True) + + def save(self, *args, **kwargs): + if not self.slug: + self.slug = slugify(self.name) + super().save(*args, **kwargs) + + def __str__(self): + return self.name + + class Meta: + verbose_name_plural = "Categories" + +class Book(models.Model): + title = models.CharField(max_length=255) + description = models.TextField() + price = models.DecimalField(max_digits=10, decimal_places=2) + pdf_file = models.FileField(upload_to='books/pdfs/') + cover_image = models.ImageField(upload_to='books/covers/', blank=True, null=True) + category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name='books') + is_featured = models.BooleanField(default=False) + created_at = models.DateTimeField(auto_now_add=True) + slug = models.SlugField(unique=True, blank=True) + + def save(self, *args, **kwargs): + if not self.slug: + self.slug = slugify(self.title) + super().save(*args, **kwargs) + + def __str__(self): + return self.title + +class Order(models.Model): + STATUS_CHOICES = ( + ('pending', 'Pending'), + ('approved', 'Approved'), + ('rejected', 'Rejected'), + ) + book = models.ForeignKey(Book, on_delete=models.CASCADE) + user_email = models.EmailField() + transaction_id = models.CharField(max_length=100, help_text="Enter your EVC/Zaad/Sahal transaction ID or reference") + payment_screenshot = models.ImageField(upload_to='payments/', blank=True, null=True) + status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='pending') + created_at = models.DateTimeField(auto_now_add=True) + + def __str__(self): + return f"Order for {self.book.title} by {self.user_email}" \ No newline at end of file diff --git a/core/templates/base.html b/core/templates/base.html index 1e7e5fb..f5c447c 100644 --- a/core/templates/base.html +++ b/core/templates/base.html @@ -1,25 +1,140 @@ +{% load static %} - - - {% block title %}Knowledge Base{% endblock %} - {% if project_description %} - - - - {% endif %} - {% if project_image_url %} - - - {% endif %} - {% load static %} - - {% block head %}{% endblock %} + + + {% block title %}Digital Bookstore | Premium PDFs{% endblock %} + + + + + + + + + + + + + + + {% block extra_css %}{% endblock %} - - {% block content %}{% endblock %} - + + - + + {% if messages %} +
+ {% for message in messages %} + + {% endfor %} +
+ {% endif %} + + +
+ {% block content %}{% endblock %} +
+ + + + + + + + {% block extra_js %}{% endblock %} + + \ No newline at end of file diff --git a/core/templates/core/about.html b/core/templates/core/about.html new file mode 100644 index 0000000..4fdf3a3 --- /dev/null +++ b/core/templates/core/about.html @@ -0,0 +1,16 @@ +{% extends "base.html" %} +{% block title %}About Us | Digital Bookstore{% endblock %} + +{% block content %} +
+
+
+

Ku soo dhawaada BookStore

+

BookStore waa maktabad dhijitaal ah oo loogu talagalay in lagu horumariyo aqoonta iyo akhriska. Waxaan bixinaa buugaag PDF ah oo tayo leh, kuwaas oo isugu jira aqoon guud, suugaan, iyo cilmi. Hadafkayagu waa inaan u fududaynno akhristayaasha helitaanka buugaagta ay u baahan yihiin si casri ah, annaga oo bixinna adeeg degdeg ah iyo lacag bixin local ah oo sugan. Waxaan aaminsannahay in aqoontu tahay furaha nolosha, sidaas darteed waxaan halkan idiinku soo ururinay buugaag run ah oo nuxur leh.

+
+

Our Vision

+

Our vision is to become the leading provider of digital educational resources in the region, bridging the gap between knowledge seekers and the tools they need to succeed.

+
+
+
+{% endblock %} diff --git a/core/templates/core/book_detail.html b/core/templates/core/book_detail.html new file mode 100644 index 0000000..5bf3076 --- /dev/null +++ b/core/templates/core/book_detail.html @@ -0,0 +1,169 @@ +{% extends "base.html" %} +{% load static %} +{% block title %}{{ book.title }} | BookStore{% endblock %} + +{% block content %} +
+
+ +
+
+ +
+
+ +
+
+
+ {% if book.cover_image %} + {{ book.title }} + {% else %} +
+ + Premium Digital Edition +
+ {% endif %} +
+ +
+
+ + PDF Format +
+
+ + Instant Access +
+
+ + Print Ready +
+
+ + +
+
Share this book
+ +
+
+
+ + +
+
+
+ + {{ book.category.name }} + +

{{ book.title }}

+ +
+
+ Special Price +

${{ book.price }}

+
+
+
+ Availability + Available for Download +
+
+
+ +
+
Description
+
+ {{ book.description|linebreaks }} +
+
+ +
+
+ +
+
+
+

Get Your Digital Copy

+

Secure payment via EVC, Zaad, or Sahal.

+
+ +
+
+ + + {% if related_books %} +
+
+

More From This Category

+ View All +
+ +
+ {% endif %} + + +
+ [Google AdSense Footer Slot] +
+
+
+
+
+ + +{% endblock %} \ No newline at end of file diff --git a/core/templates/core/book_list.html b/core/templates/core/book_list.html new file mode 100644 index 0000000..a3a2458 --- /dev/null +++ b/core/templates/core/book_list.html @@ -0,0 +1,128 @@ +{% extends "base.html" %} +{% load static %} +{% block title %}Explore Digital Library | BookStore{% endblock %} + +{% block content %} +
+
+ +

Browse Our Collection

+

Discover the best digital books across all categories.

+
+
+ +
+
+ + + + +
+ +
+
+
+ {% if selected_category %} + Category: {{ selected_category|capfirst }} + {% else %} + All Available Books + {% endif %} +
+

Showing {{ books.count }} results found

+
+
+ +
+ + {% if selected_category %} + + {% endif %} +
+
+
+ +
+ {% for book in books %} +
+
+
+ {% if book.cover_image %} + {{ book.title }} + {% else %} +
+ +
+ {% endif %} +
+ ${{ book.price }} +
+
+
+

{{ book.category.name }}

+
{{ book.title }}
+ +
+
+
+ {% empty %} +
+
+ +

No Books Found

+

Try adjusting your search or category filters.

+ Reset Filters +
+
+ {% endfor %} +
+ + +
+ [Google AdSense Footer Slot] +
+
+
+
+ + +{% endblock %} \ No newline at end of file diff --git a/core/templates/core/checkout.html b/core/templates/core/checkout.html new file mode 100644 index 0000000..ccde5b7 --- /dev/null +++ b/core/templates/core/checkout.html @@ -0,0 +1,159 @@ +{% extends "base.html" %} +{% load static %} +{% block title %}Secure Checkout | BookStore{% endblock %} + +{% block content %} +
+
+

Complete Your Purchase

+

Secure your copy of "{{ book.title }}" in just a few steps.

+
+
+ +
+
+ +
+
+
+
Order Summary
+
+
+
+ {% if book.cover_image %} + + {% else %} +
+ +
+ {% endif %} +
+
{{ book.title }}
+

{{ book.category.name }}

+ Digital PDF +
+
+ +
+ Item Price + ${{ book.price }} +
+
+ Transaction Fee + FREE +
+ +
+ +
+
Total Amount
+

${{ book.price }}

+
+
+
+

Secure checkout provided by BookStore

+
+
+
+ + +
+
+ +
+
+ 1 +
Payment Instructions
+
+ +
+
+ +
+

Send your payment to:

+
+
+
+
+ +
+
+ ZAAD / SAHAL / EVC PLUS + +252 63 4844506 +
+
+
+
+

+ + After transfer, please keep your Transaction ID ready to enter below. +

+
+
+ + +
+
+ 2 +
Verification Details
+
+ +
+ {% csrf_token %} +
+ +
+ + +
+
We'll never share your email with anyone else.
+
+ +
+ +
+ + +
+
+ +
+ + +
Adding a screenshot helps us verify your payment faster.
+
+ + +
+
+ + +
+
+
+ + SECURE PAYMENT +
+
+ + INSTANT ACCESS +
+
+ + VERIFIED SELLER +
+
+
+ + + +
+
+
+
+{% endblock %} \ No newline at end of file diff --git a/core/templates/core/contact.html b/core/templates/core/contact.html new file mode 100644 index 0000000..34898e9 --- /dev/null +++ b/core/templates/core/contact.html @@ -0,0 +1,63 @@ +{% extends "base.html" %} +{% block title %}Contact Us | Digital Bookstore{% endblock %} + +{% block content %} +
+
+

Get in Touch

+

We're here to help you with your digital book experience.

+
+
+ +
+
+
+
+
+ +
+

Support & Inquiries

+

Have questions about a book or your order? Reach out to our team through any of the channels below.

+ +
+
+
+ +
+
+ WhatsApp Support + +252 63 4844506 +
+
+ +
+
+ +
+
+ Email Address + support@bookstore.com +
+
+ +
+
+ +
+
+ Headquarters + Hargeisa, Somalia +
+
+
+ + +
+
+
+
+{% endblock %} \ No newline at end of file diff --git a/core/templates/core/index.html b/core/templates/core/index.html index faec813..fb4b17e 100644 --- a/core/templates/core/index.html +++ b/core/templates/core/index.html @@ -1,145 +1,227 @@ {% extends "base.html" %} - -{% block title %}{{ project_name }}{% endblock %} - -{% block head %} - - - - -{% endblock %} +{% load static %} +{% block title %}Home | Digital Bookstore - Premium PDFs{% endblock %} {% block content %} -
-
-

Analyzing your requirements and generating your app…

-
- Loading… + +
+
+
+
+ NEW ARRIVALS 2026 +

+ Find Your Next Great Adventure In A Book. +

+

+ Explore our curated collection of high-quality digital books. From educational resources to classic literature, we have it all. +

+
+
+ + + +
+
+
+ Instant Download + Secure Payment + Premium Quality +
+
+
+
+ +
+
+
+ Hero Books +
+
+
+
-

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" }} -

-
-
- + + + +
+
+
+

Browse Categories

+

Find books by your favorite genres

+
+ + View All + +
+
+ {% for category in categories %} + + {% empty %} + +
+
+ +
Educational
+
+
+
+
+ +
Literature
+
+
+
+
+ +
History
+
+
+
+
+ +
Business
+
+
+ {% endfor %} +
+
+ + +
+
+

Featured Collections

+

Our hand-picked selections for you

+
+ +
+ {% for book in featured_books %} +
+
+
+ {% if book.cover_image %} + {{ book.title }} + {% else %} +
+ +
+ {% endif %} +
+ ${{ book.price }} +
+
+
+

{{ book.category.name }}

+
{{ book.title }}
+ +
+
+
+ {% empty %} +
+
+ +

Our shelves are being stocked. Check back soon!

+ Add First Book +
+
+ {% endfor %} +
+
+ + +
+
+
+
+
+ +
Instant Access
+

Download your books immediately after payment confirmation. No waiting, no shipping.

+
+
+
+
+ +
Secure Payment
+

We support EVC Plus, Zaad, and Sahal. Your transactions are safe and verified manually.

+
+
+
+
+ +
Premium Support
+

Need help with your download? Our team is available 24/7 to assist you via WhatsApp.

+
+
+
+
+
+ + +
+
+ + Sponsorship Space Available +
+
+ + {% endblock %} \ No newline at end of file diff --git a/core/templates/core/order_success.html b/core/templates/core/order_success.html new file mode 100644 index 0000000..4e5926a --- /dev/null +++ b/core/templates/core/order_success.html @@ -0,0 +1,26 @@ +{% extends "base.html" %} +{% block title %}Order Successful | Digital Bookstore{% endblock %} + +{% block content %} +
+
+
+
+

Order Success!

+

Thank you for your purchase. We have received your order and are currently verifying your payment.

+
+
Next Steps:
+
    +
  • 1. Our team will verify your transaction ID.
  • +
  • 2. Once verified, we will email you the download link.
  • +
  • 3. Check your inbox and spam folder for the book.
  • +
+
+ +
+
+
+
+{% endblock %} diff --git a/core/templates/core/privacy.html b/core/templates/core/privacy.html new file mode 100644 index 0000000..74ebaa1 --- /dev/null +++ b/core/templates/core/privacy.html @@ -0,0 +1,17 @@ +{% extends "base.html" %} +{% block title %}Privacy Policy | Digital Bookstore{% endblock %} + +{% block content %} +
+
+
+

Privacy Policy

+

At BookStore, we value your privacy. We collect minimal information such as your name and email when you register or purchase a book to process your order.

+

Cookies & Ads

+

We use Google AdSense to show ads. Third-party vendors, including Google, use cookies to serve ads based on your prior visits to our website. You can opt-out of personalized advertising by visiting Google Ads Settings.

+

Data Protection

+

We do not sell or share your personal data with third parties. All local payment transactions are processed through secure gateways.

+
+
+
+{% endblock %} diff --git a/core/templates/core/terms.html b/core/templates/core/terms.html new file mode 100644 index 0000000..00f3d48 --- /dev/null +++ b/core/templates/core/terms.html @@ -0,0 +1,18 @@ +{% extends "base.html" %} +{% block title %}Terms & Conditions | Digital Bookstore{% endblock %} + +{% block content %} +
+
+
+

Terms & Conditions

+

Isticmaalka website-kan waxay ka dhigantahay inaad ku raacday shuruudaha soo socda:

+
    +
  • Buugaagta aad halkan ka iibsanayso ama ka soo dagsanayso waa isticmaalkaaga gaarka ah (Personal use only).
  • +
  • Lama ogola in dib loo iibiyo ama loo qaybiyo buugaagta adiga oo aan oggolaansho ka helin maamulka.
  • +
  • Lacagaha la bixiyo dib looma soo celiyo maadaama badeecadu tahay mid dhijitaal ah (Digital product).
  • +
+
+
+
+{% endblock %} diff --git a/core/urls.py b/core/urls.py index 6299e3d..aaff40a 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 urlpatterns = [ - path("", home, name="home"), -] + path("", views.home, name="home"), + path("books/", views.book_list, name="book_list"), + path("book//", views.book_detail, name="book_detail"), + path("book//checkout/", views.checkout, name="checkout"), + path("order-success/", views.order_success, name="order_success"), + path("about/", views.about, name="about"), + path("contact/", views.contact, name="contact"), + path("privacy/", views.privacy, name="privacy"), + path("terms/", views.terms, name="terms"), +] \ No newline at end of file diff --git a/core/views.py b/core/views.py index c9aed12..62c589f 100644 --- a/core/views.py +++ b/core/views.py @@ -1,25 +1,75 @@ -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, get_object_or_404, redirect +from .models import Category, Book, Order +from django.db.models import Q +from django.contrib import messages 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() + featured_books = Book.objects.filter(is_featured=True)[:6] + if not featured_books.exists(): + featured_books = Book.objects.all()[:6] + categories = Category.objects.all() + return render(request, "core/index.html", { + "featured_books": featured_books, + "categories": categories, + }) - 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) +def book_list(request): + query = request.GET.get('q') + category_slug = request.GET.get('category') + books = Book.objects.all() + categories = Category.objects.all() + + if query: + books = books.filter(Q(title__icontains=query) | Q(description__icontains=query)) + if category_slug: + books = books.filter(category__slug=category_slug) + + return render(request, "core/book_list.html", { + "books": books, + "categories": categories, + "selected_category": category_slug, + }) + +def book_detail(request, slug): + book = get_object_or_404(Book, slug=slug) + related_books = Book.objects.filter(category=book.category).exclude(id=book.id)[:4] + return render(request, "core/book_detail.html", { + "book": book, + "related_books": related_books, + }) + +def checkout(request, slug): + book = get_object_or_404(Book, slug=slug) + if request.method == 'POST': + email = request.POST.get('email') + transaction_id = request.POST.get('transaction_id') + screenshot = request.FILES.get('screenshot') + + if email and transaction_id: + Order.objects.create( + book=book, + user_email=email, + transaction_id=transaction_id, + payment_screenshot=screenshot + ) + messages.success(request, "Your order has been submitted. We will verify your payment and email you the download link.") + return redirect('order_success') + else: + messages.error(request, "Please fill in all required fields.") + + return render(request, "core/checkout.html", {"book": book}) + +def order_success(request): + return render(request, "core/order_success.html") + +def about(request): + return render(request, "core/about.html") + +def contact(request): + return render(request, "core/contact.html") + +def privacy(request): + return render(request, "core/privacy.html") + +def terms(request): + return render(request, "core/terms.html") \ No newline at end of file diff --git a/media/books/covers/old-logo.png b/media/books/covers/old-logo.png new file mode 100644 index 0000000..4fc7fad Binary files /dev/null and b/media/books/covers/old-logo.png differ diff --git a/media/books/pdfs/old-logo.png b/media/books/pdfs/old-logo.png new file mode 100644 index 0000000..4fc7fad Binary files /dev/null and b/media/books/pdfs/old-logo.png differ diff --git a/media/categories/old-logo.png b/media/categories/old-logo.png new file mode 100644 index 0000000..4fc7fad Binary files /dev/null and b/media/categories/old-logo.png differ diff --git a/media/payments/old-logo.png b/media/payments/old-logo.png new file mode 100644 index 0000000..4fc7fad Binary files /dev/null and b/media/payments/old-logo.png differ diff --git a/media/payments/old-logo_Ra7wrGc.png b/media/payments/old-logo_Ra7wrGc.png new file mode 100644 index 0000000..4fc7fad Binary files /dev/null and b/media/payments/old-logo_Ra7wrGc.png differ diff --git a/static/css/custom.css b/static/css/custom.css index 925f6ed..bba000e 100644 --- a/static/css/custom.css +++ b/static/css/custom.css @@ -1,4 +1,186 @@ -/* Custom styles for the application */ -body { - font-family: system-ui, -apple-system, sans-serif; +/* Global Styles */ +:root { + --primary: #0D6EFD; + --primary-light: #E7F0FF; + --accent: #FF9F1C; + --dark: #1D3557; + --text-muted: #6C757D; + --bg-body: #F8F9FA; + --radius-sm: 8px; + --radius-md: 16px; + --radius-lg: 24px; + --shadow-soft: 0 10px 30px rgba(0, 0, 0, 0.05); + --transition-base: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); } + +body { + font-family: 'Plus Jakarta Sans', sans-serif; + background-color: var(--bg-body); + color: var(--dark); + line-height: 1.6; + overflow-x: hidden; +} + +h1, h2, h3, h4, h5, h6 { + font-weight: 700; + letter-spacing: -0.02em; +} + +/* Glassmorphism Effect */ +.bg-glass { + background: rgba(255, 255, 255, 0.85); + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); + border-bottom: 1px solid rgba(255, 255, 255, 0.2); + transition: var(--transition-base); +} + +/* Gradient Text */ +.text-primary-gradient { + background: linear-gradient(135deg, var(--primary) 0%, #00B4D8 100%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; +} + +/* Buttons */ +.btn-primary { + background-color: var(--primary); + border: none; + border-radius: var(--radius-lg); + padding: 0.8rem 1.8rem; + font-weight: 600; + transition: var(--transition-base); +} + +.btn-primary:hover { + background-color: #0056b3; + transform: translateY(-2px); + box-shadow: 0 8px 15px rgba(13, 110, 253, 0.2); +} + +.btn-outline-dark { + border-radius: var(--radius-lg); + border: 2px solid var(--dark); + font-weight: 600; + transition: var(--transition-base); +} + +.btn-outline-dark:hover { + background-color: var(--dark); + transform: translateY(-2px); +} + +/* Hero Section */ +.hero-section { + background: linear-gradient(180deg, #FFFFFF 0%, #F1F4F9 100%); + position: relative; + overflow: hidden; +} + +.hero-section::after { + content: ''; + position: absolute; + width: 600px; + height: 600px; + background: radial-gradient(circle, rgba(13, 110, 253, 0.03) 0%, rgba(13, 110, 253, 0) 70%); + top: -200px; + right: -200px; + z-index: 0; +} + +/* Book Card */ +.book-card { + background: #FFFFFF; + border: none; + border-radius: var(--radius-md); + overflow: hidden; + transition: var(--transition-base); + box-shadow: var(--shadow-soft); +} + +.book-card:hover { + transform: translateY(-10px); + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.08); +} + +.book-card img { + border-radius: var(--radius-md) var(--radius-md) 0 0; + transition: transform 0.6s ease; +} + +.book-card:hover img { + transform: scale(1.05); +} + +.book-card .card-body { + padding: 1.5rem; +} + +/* Search Box */ +.search-box-wrap { + background: #FFFFFF; + border-radius: var(--radius-lg); + padding: 8px; + box-shadow: var(--shadow-soft); +} + +.search-box-wrap input { + border: none; + background: transparent; +} + +.search-box-wrap input:focus { + box-shadow: none; +} + +/* Category Pill */ +.category-pill { + background: #FFFFFF; + border-radius: var(--radius-md); + padding: 1.5rem; + text-align: center; + transition: var(--transition-base); + box-shadow: var(--shadow-soft); + border: 1px solid transparent; +} + +.category-pill:hover { + border-color: var(--primary); + transform: translateY(-5px); +} + +/* Hover Primary */ +.hover-primary { + transition: var(--transition-base); +} + +.hover-primary:hover { + color: var(--primary) !important; +} + +/* Custom Utilities */ +.rounded-pill-start { + border-top-left-radius: 50px; + border-bottom-left-radius: 50px; +} + +.rounded-pill-end { + border-top-right-radius: 50px; + border-bottom-right-radius: 50px; +} + +/* Animation */ +@keyframes fadeInUp { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.fade-in-up { + animation: fadeInUp 0.8s ease forwards; +} \ No newline at end of file