Compare commits

...

1 Commits

Author SHA1 Message Date
Flatlogic Bot
9560e61e41 Autosave: 20260219-193434 2026-02-19 19:34:34 +00:00
32 changed files with 1403 additions and 208 deletions

View File

@ -180,3 +180,7 @@ if EMAIL_USE_SSL:
# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field # https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
# Media files (Uploads)
MEDIA_URL = 'media/'
MEDIA_ROOT = BASE_DIR / 'media'

View File

@ -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.contrib import admin
from django.urls import include, path from django.urls import include, path
from django.conf import settings from django.conf import settings
@ -25,5 +9,5 @@ urlpatterns = [
] ]
if settings.DEBUG: if settings.DEBUG:
urlpatterns += static("/assets/", document_root=settings.BASE_DIR / "assets") urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

View File

@ -1,3 +1,53 @@
from django.contrib import admin 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('<img src="{}" style="width: 40px; height: 40px; border-radius: 50%;" />', 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('<img src="{}" style="width: 50px; height: 70px; border-radius: 4px;" />', 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('<a href="{}" target="_blank"><img src="{}" style="width: 50px; height: 50px; border-radius: 4px;" /></a>', obj.payment_screenshot.url, obj.payment_screenshot.url)
return "No Proof"
display_screenshot.short_description = 'Payment Proof'

View File

@ -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')),
],
),
]

View File

@ -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/'),
),
]

View File

@ -1,3 +1,53 @@
from django.db import models 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}"

View File

@ -1,25 +1,140 @@
{% load static %}
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>{% block title %}Knowledge Base{% endblock %}</title> <meta name="viewport" content="width=device-width, initial-scale=1.0">
{% if project_description %} <title>{% block title %}Digital Bookstore | Premium PDFs{% endblock %}</title>
<meta name="description" content="{{ project_description }}"> <meta name="description" content="{% block meta_description %}Buy and download high-quality PDF books online. Safe, fast, and secure.{% endblock %}">
<meta property="og:description" content="{{ project_description }}">
<meta property="twitter:description" content="{{ project_description }}"> <!-- Google Fonts -->
{% endif %} <link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@300;400;500;600;700;800&display=swap" rel="stylesheet">
{% if project_image_url %}
<meta property="og:image" content="{{ project_image_url }}"> <!-- Font Awesome -->
<meta property="twitter:image" content="{{ project_image_url }}"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
{% endif %}
{% load static %} <!-- Bootstrap 5 CSS CDN -->
<link rel="stylesheet" href="{% static 'css/custom.css' %}?v={{ deployment_timestamp }}"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
{% block head %}{% endblock %}
<!-- Custom CSS -->
<link rel="stylesheet" href="{% static 'css/custom.css' %}?v={{ deployment_timestamp }}">
{% block extra_css %}{% endblock %}
</head> </head>
<body> <body>
{% block content %}{% endblock %} <!-- Navbar -->
</body> <nav class="navbar navbar-expand-lg sticky-top navbar-light bg-glass py-3">
<div class="container">
<a class="navbar-brand fw-bold fs-3" href="{% url 'home' %}">
<span class="text-primary-gradient">Book</span><span class="text-dark">Store</span>
</a>
<button class="navbar-toggler border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto align-items-center">
<li class="nav-item"><a class="nav-link px-3" href="{% url 'home' %}">Home</a></li>
<li class="nav-item"><a class="nav-link px-3" href="{% url 'book_list' %}">Explore</a></li>
<li class="nav-item"><a class="nav-link px-3" href="{% url 'about' %}">About</a></li>
<li class="nav-item"><a class="nav-link px-3" href="{% url 'contact' %}">Contact</a></li>
<li class="nav-item ms-lg-3">
<a href="/admin/" class="btn btn-dark rounded-pill px-4 shadow-sm" target="_blank">
<i class="fas fa-user-shield me-2"></i>Admin
</a>
</li>
</ul>
</div>
</div>
</nav>
</html> <!-- Messaging System -->
{% if messages %}
<div class="container mt-4">
{% for message in messages %}
<div class="alert alert-{{ message.tags }} alert-dismissible fade show rounded-4 shadow-sm border-0" role="alert">
<i class="fas {% if message.tags == 'success' %}fa-check-circle{% else %}fa-exclamation-circle{% endif %} me-2"></i>
{{ message }}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
{% endfor %}
</div>
{% endif %}
<!-- Main Content -->
<main>
{% block content %}{% endblock %}
</main>
<!-- Footer -->
<footer class="footer bg-white pt-5 pb-3 mt-5 border-top">
<div class="container">
<div class="row g-4">
<div class="col-lg-4">
<a class="navbar-brand fw-bold fs-3 d-block mb-3" href="{% url 'home' %}">
<span class="text-primary-gradient">Book</span><span class="text-dark">Store</span>
</a>
<p class="text-muted pe-lg-5">Your premium destination for high-quality digital PDF books. Empowering knowledge sharing across the globe.</p>
<div class="social-links d-flex gap-3 mt-4">
<a href="https://wa.me/252634844506" class="btn btn-sm btn-outline-success rounded-circle" target="_blank"><i class="fab fa-whatsapp"></i></a>
<a href="#" class="btn btn-sm btn-outline-primary rounded-circle"><i class="fab fa-facebook-f"></i></a>
<a href="#" class="btn btn-sm btn-outline-info rounded-circle"><i class="fab fa-twitter"></i></a>
<a href="#" class="btn btn-sm btn-outline-danger rounded-circle"><i class="fab fa-instagram"></i></a>
</div>
</div>
<div class="col-lg-2 col-md-4">
<h6 class="fw-bold mb-4">Quick Links</h6>
<ul class="list-unstyled">
<li class="mb-2"><a href="{% url 'home' %}" class="text-muted text-decoration-none hover-primary">Home</a></li>
<li class="mb-2"><a href="{% url 'book_list' %}" class="text-muted text-decoration-none hover-primary">All Books</a></li>
<li class="mb-2"><a href="{% url 'about' %}" class="text-muted text-decoration-none hover-primary">Our Story</a></li>
<li class="mb-2"><a href="{% url 'contact' %}" class="text-muted text-decoration-none hover-primary">Contact Us</a></li>
</ul>
</div>
<div class="col-lg-3 col-md-4">
<h6 class="fw-bold mb-4">Legal</h6>
<ul class="list-unstyled">
<li class="mb-2"><a href="{% url 'privacy' %}" class="text-muted text-decoration-none hover-primary">Privacy Policy</a></li>
<li class="mb-2"><a href="{% url 'terms' %}" class="text-muted text-decoration-none hover-primary">Terms & Conditions</a></li>
</ul>
</div>
<div class="col-lg-3 col-md-4">
<h6 class="fw-bold mb-4">Contact Support</h6>
<p class="small text-muted mb-3">Reach out to us via WhatsApp for instant support.</p>
<div class="d-grid">
<a href="https://wa.me/252634844506" class="btn btn-success rounded-pill fw-bold">
<i class="fab fa-whatsapp me-2"></i> +252 63 4844506
</a>
</div>
</div>
</div>
<hr class="my-4 text-muted opacity-25">
<div class="d-flex flex-column flex-md-row justify-content-between align-items-center gap-3">
<p class="text-muted small mb-0">&copy; 2026 BookStore. All rights reserved.</p>
<div class="payment-icons d-flex gap-3 text-muted opacity-50">
<span class="small fw-bold me-2">Payments:</span>
<i class="fas fa-mobile-screen-button fa-lg" title="EVC Plus"></i>
<i class="fas fa-wallet fa-lg" title="Zaad"></i>
<i class="fab fa-whatsapp fa-lg" title="Order via WhatsApp"></i>
</div>
</div>
</div>
</footer>
<!-- Bootstrap 5 JS Bundle -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script>
// Scroll interaction for glass navbar
window.addEventListener('scroll', function() {
const nav = document.querySelector('.navbar');
if (window.scrollY > 50) {
nav.classList.add('shadow-sm');
nav.style.padding = '0.5rem 0';
} else {
nav.classList.remove('shadow-sm');
nav.style.padding = '1rem 0';
}
});
</script>
{% block extra_js %}{% endblock %}
</body>
</html>

View File

@ -0,0 +1,16 @@
{% extends "base.html" %}
{% block title %}About Us | Digital Bookstore{% endblock %}
{% block content %}
<div class="container py-5">
<div class="row justify-content-center">
<div class="col-md-8">
<h1 class="mb-4">Ku soo dhawaada BookStore</h1>
<p class="lead">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.</p>
<hr class="my-5">
<h3 class="mb-4 text-center">Our Vision</h3>
<p class="text-center">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.</p>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,169 @@
{% extends "base.html" %}
{% load static %}
{% block title %}{{ book.title }} | BookStore{% endblock %}
{% block content %}
<header class="bg-white border-bottom py-4 mb-5">
<div class="container py-2">
<nav aria-label="breadcrumb">
<ol class="breadcrumb mb-0 small">
<li class="breadcrumb-item"><a href="{% url 'home' %}" class="text-decoration-none text-muted">Home</a></li>
<li class="breadcrumb-item"><a href="{% url 'book_list' %}" class="text-decoration-none text-muted">Explore</a></li>
<li class="breadcrumb-item"><a href="{% url 'book_list' %}?category={{ book.category.slug }}" class="text-decoration-none text-muted">{{ book.category.name }}</a></li>
<li class="breadcrumb-item active fw-bold text-primary" aria-current="page">{{ book.title|truncatechars:30 }}</li>
</ol>
</nav>
</div>
</header>
<div class="container mb-5 pb-5">
<div class="row g-5">
<!-- Book Cover (Left) -->
<div class="col-lg-5">
<div class="position-sticky" style="top: 100px;">
<div class="card border-0 shadow-lg rounded-4 overflow-hidden bg-white p-3">
{% if book.cover_image %}
<img src="{{ book.cover_image.url }}" class="img-fluid rounded-4 shadow-sm w-100" alt="{{ book.title }}" style="min-height: 500px; object-fit: cover;">
{% else %}
<div class="bg-light rounded-4 d-flex flex-column align-items-center justify-content-center shadow-sm w-100" style="min-height: 500px;">
<i class="fas fa-book-open fa-5x text-muted opacity-25 mb-4"></i>
<span class="text-muted fw-bold">Premium Digital Edition</span>
</div>
{% endif %}
</div>
<div class="d-flex justify-content-center gap-4 mt-4 text-muted small px-3">
<div class="text-center">
<i class="far fa-file-pdf fa-2x mb-2 d-block text-danger"></i>
<span>PDF Format</span>
</div>
<div class="text-center">
<i class="fas fa-bolt fa-2x mb-2 d-block text-warning"></i>
<span>Instant Access</span>
</div>
<div class="text-center">
<i class="fas fa-print fa-2x mb-2 d-block text-success"></i>
<span>Print Ready</span>
</div>
</div>
<!-- Share Section -->
<div class="mt-5 p-4 bg-white rounded-4 shadow-soft text-center border">
<h6 class="fw-bold mb-3 text-uppercase small letter-spacing-1 text-muted">Share this book</h6>
<div class="d-flex justify-content-center gap-3">
<a href="https://api.whatsapp.com/send?text=Check out this amazing book: {{ book.title }} - {{ request.build_absolute_uri }}" target="_blank" class="btn btn-whatsapp rounded-circle d-flex align-items-center justify-content-center shadow-sm" style="width: 50px; height: 50px; background-color: #25D366; color: white;">
<i class="fab fa-whatsapp fa-lg"></i>
</a>
<a href="https://www.facebook.com/sharer/sharer.php?u={{ request.build_absolute_uri }}" target="_blank" class="btn btn-facebook rounded-circle d-flex align-items-center justify-content-center shadow-sm" style="width: 50px; height: 50px; background-color: #1877F2; color: white;">
<i class="fab fa-facebook-f fa-lg"></i>
</a>
<a href="https://twitter.com/intent/tweet?text=Reading {{ book.title }}&url={{ request.build_absolute_uri }}" target="_blank" class="btn btn-twitter rounded-circle d-flex align-items-center justify-content-center shadow-sm" style="width: 50px; height: 50px; background-color: #1DA1F2; color: white;">
<i class="fab fa-twitter fa-lg"></i>
</a>
</div>
</div>
</div>
</div>
<!-- Book Details (Right) -->
<div class="col-lg-7">
<div class="ps-lg-4">
<div class="mb-4">
<span class="badge bg-primary-light text-primary px-3 py-2 rounded-pill fw-bold mb-3 d-inline-block text-uppercase letter-spacing-1">
{{ book.category.name }}
</span>
<h1 class="display-4 fw-800 text-dark mb-4 lh-sm">{{ book.title }}</h1>
<div class="d-flex align-items-center mb-5 gap-4">
<div class="price-wrap">
<span class="text-muted small d-block mb-1 fw-bold text-uppercase">Special Price</span>
<h2 class="fw-800 text-primary mb-0 fs-1">${{ book.price }}</h2>
</div>
<div class="vr mx-3 opacity-10 d-none d-md-block" style="height: 50px;"></div>
<div class="stock-info">
<span class="text-muted small d-block mb-1 fw-bold text-uppercase">Availability</span>
<span class="text-success fw-bold"><i class="fas fa-check-circle me-1"></i> Available for Download</span>
</div>
</div>
</div>
<div class="mb-5">
<h5 class="fw-bold mb-3 border-bottom pb-2">Description</h5>
<div class="lead text-muted lh-lg" style="font-size: 1.1rem;">
{{ book.description|linebreaks }}
</div>
</div>
<div class="cta-wrap bg-light p-4 p-md-5 rounded-4 border-0 mb-5 position-relative overflow-hidden">
<div class="position-absolute top-0 end-0 p-4 opacity-10">
<i class="fas fa-cart-shopping fa-6x"></i>
</div>
<div class="row align-items-center position-relative">
<div class="col-md-7 mb-4 mb-md-0">
<h4 class="fw-800 mb-2">Get Your Digital Copy</h4>
<p class="text-muted mb-0 small">Secure payment via EVC, Zaad, or Sahal.</p>
</div>
<div class="col-md-5 text-md-end d-flex flex-column gap-2">
<a href="{% url 'checkout' book.slug %}" class="btn btn-primary btn-lg rounded-pill px-4 shadow-lg py-3 fw-bold w-100">
Buy Now <i class="fas fa-arrow-right ms-2"></i>
</a>
<a href="https://wa.me/252634844506?text=I'm interested in buying: {{ book.title }}" target="_blank" class="btn btn-outline-success btn-lg rounded-pill px-4 py-3 fw-bold w-100">
<i class="fab fa-whatsapp me-2"></i> Chat to Buy
</a>
</div>
</div>
</div>
<!-- Related Books Section -->
{% if related_books %}
<div class="mt-5 pt-5 border-top">
<div class="d-flex justify-content-between align-items-center mb-4">
<h4 class="fw-bold mb-0">More From This Category</h4>
<a href="{% url 'book_list' %}?category={{ book.category.slug }}" class="btn btn-link text-decoration-none fw-bold text-primary small">View All</a>
</div>
<div class="row g-4">
{% for r_book in related_books %}
<div class="col-md-3 col-6">
<a href="{% url 'book_detail' r_book.slug %}" class="text-decoration-none">
<div class="card book-card h-100 border-0 shadow-soft">
{% if r_book.cover_image %}
<img src="{{ r_book.cover_image.url }}" class="card-img-top rounded-3" alt="{{ r_book.title }}" style="height: 180px; object-fit: cover;">
{% else %}
<div class="card-img-top bg-light rounded-3 d-flex align-items-center justify-content-center" style="height: 180px;">
<i class="fas fa-book text-muted opacity-25"></i>
</div>
{% endif %}
<div class="card-body p-3">
<h6 class="card-title fw-bold text-dark mb-1 small line-clamp-2">{{ r_book.title }}</h6>
<span class="text-primary fw-bold small">${{ r_book.price }}</span>
</div>
</div>
</a>
</div>
{% endfor %}
</div>
</div>
{% endif %}
<!-- AdSense Content Slot -->
<div class="adsense-slot mt-5 rounded-4 border-0 bg-white shadow-soft p-5 text-center text-muted small">
[Google AdSense Footer Slot]
</div>
</div>
</div>
</div>
</div>
<style>
.line-clamp-2 {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
.btn-whatsapp:hover, .btn-facebook:hover, .btn-twitter:hover {
transform: translateY(-5px);
transition: transform 0.3s ease;
}
</style>
{% endblock %}

View File

@ -0,0 +1,128 @@
{% extends "base.html" %}
{% load static %}
{% block title %}Explore Digital Library | BookStore{% endblock %}
{% block content %}
<header class="bg-white border-bottom py-5 mb-5">
<div class="container py-4">
<nav aria-label="breadcrumb">
<ol class="breadcrumb mb-2 small">
<li class="breadcrumb-item"><a href="{% url 'home' %}" class="text-decoration-none text-muted">Home</a></li>
<li class="breadcrumb-item active fw-bold text-primary" aria-current="page">Explore Library</li>
</ol>
</nav>
<h1 class="fw-800 display-5 mb-0">Browse Our <span class="text-primary-gradient">Collection</span></h1>
<p class="text-muted fs-5 mt-2">Discover the best digital books across all categories.</p>
</div>
</header>
<div class="container mb-5">
<div class="row g-5">
<!-- Sidebar Filter -->
<div class="col-lg-3">
<div class="sticky-top" style="top: 100px; z-index: 10;">
<h6 class="fw-bold text-uppercase letter-spacing-1 mb-4 small text-muted">Filter By Category</h6>
<div class="list-group list-group-flush shadow-soft rounded-4 overflow-hidden border">
<a href="{% url 'book_list' %}" class="list-group-item list-group-item-action py-3 px-4 border-0 d-flex justify-content-between align-items-center {% if not selected_category %}bg-primary text-white fw-bold shadow-sm{% else %}text-dark hover-primary{% endif %}">
All Books
{% if not selected_category %}<i class="fas fa-check-circle"></i>{% endif %}
</a>
{% for category in categories %}
<a href="{% url 'book_list' %}?category={{ category.slug }}" class="list-group-item list-group-item-action py-3 px-4 border-0 d-flex justify-content-between align-items-center {% if selected_category == category.slug %}bg-primary text-white fw-bold shadow-sm{% else %}text-dark hover-primary{% endif %}">
{{ category.name }}
{% if selected_category == category.slug %}
<i class="fas fa-check-circle"></i>
{% else %}
<span class="badge bg-light text-muted rounded-pill small fw-normal">{{ category.books.count }}</span>
{% endif %}
</a>
{% endfor %}
</div>
<!-- AdSense Sidebar Slot -->
<div class="adsense-slot mt-5 rounded-4 border-0 bg-white shadow-soft p-4 text-center text-muted small opacity-75">
<i class="fas fa-bullhorn mb-2 d-block"></i>
Partner Spotlight
</div>
</div>
</div>
<!-- Main Content -->
<div class="col-lg-9">
<!-- Search & Info Bar -->
<div class="d-flex flex-column flex-md-row justify-content-between align-items-md-center mb-5 gap-4">
<div>
<h5 class="fw-bold mb-1">
{% if selected_category %}
Category: <span class="text-primary">{{ selected_category|capfirst }}</span>
{% else %}
All Available Books
{% endif %}
</h5>
<p class="text-muted small mb-0">Showing {{ books.count }} results found</p>
</div>
<div class="search-box-wrap d-flex border align-items-center px-3 py-1 rounded-pill bg-white shadow-sm" style="min-width: 300px;">
<i class="fas fa-search text-muted me-2 small"></i>
<form action="{% url 'book_list' %}" method="GET" class="w-100">
<input type="text" name="q" class="form-control border-0 bg-transparent py-2 shadow-none small" placeholder="Quick search..." value="{{ request.GET.q }}">
{% if selected_category %}
<input type="hidden" name="category" value="{{ selected_category }}">
{% endif %}
</form>
</div>
</div>
<div class="row g-4">
{% for book in books %}
<div class="col-md-4 col-sm-6">
<div class="card book-card h-100">
<div class="position-relative">
{% if book.cover_image %}
<img src="{{ book.cover_image.url }}" class="card-img-top" alt="{{ book.title }}" style="height: 300px; object-fit: cover;">
{% else %}
<div class="card-img-top bg-light d-flex align-items-center justify-content-center" style="height: 300px;">
<i class="fas fa-book fa-3x text-muted opacity-25"></i>
</div>
{% endif %}
<div class="position-absolute top-0 end-0 m-3">
<span class="badge bg-white text-dark shadow-sm rounded-pill fw-bold px-3 py-2 border small">${{ book.price }}</span>
</div>
</div>
<div class="card-body">
<p class="text-primary small fw-bold mb-2 text-uppercase letter-spacing-1" style="font-size: 0.75rem;">{{ book.category.name }}</p>
<h6 class="card-title fw-bold text-dark mb-3 line-clamp-2" style="font-size: 1.05rem;">{{ book.title }}</h6>
<div class="d-grid mt-auto">
<a href="{% url 'book_detail' book.slug %}" class="btn btn-outline-dark rounded-pill py-2 small fw-bold">View Details</a>
</div>
</div>
</div>
</div>
{% empty %}
<div class="col-12 text-center py-5">
<div class="bg-white p-5 rounded-4 shadow-soft">
<i class="fas fa-search-minus fa-3x text-muted mb-4"></i>
<h4 class="fw-bold">No Books Found</h4>
<p class="lead text-muted">Try adjusting your search or category filters.</p>
<a href="{% url 'book_list' %}" class="btn btn-primary rounded-pill px-5 mt-3">Reset Filters</a>
</div>
</div>
{% endfor %}
</div>
<!-- AdSense Middle Slot -->
<div class="adsense-slot mt-5 rounded-4 border-0 bg-white shadow-soft p-5 text-center text-muted small">
[Google AdSense Footer Slot]
</div>
</div>
</div>
</div>
<style>
.line-clamp-2 {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
</style>
{% endblock %}

View File

@ -0,0 +1,159 @@
{% extends "base.html" %}
{% load static %}
{% block title %}Secure Checkout | BookStore{% endblock %}
{% block content %}
<section class="bg-white border-bottom py-5 mb-5">
<div class="container py-4">
<h1 class="fw-800 display-5 mb-0 text-center">Complete Your <span class="text-primary-gradient">Purchase</span></h1>
<p class="text-muted fs-5 mt-2 text-center">Secure your copy of "{{ book.title }}" in just a few steps.</p>
</div>
</section>
<div class="container mb-5 pb-5">
<div class="row g-5 justify-content-center">
<!-- Order Summary (Left) -->
<div class="col-lg-4 order-lg-2">
<div class="card border-0 shadow-soft rounded-4 overflow-hidden sticky-top" style="top: 100px;">
<div class="p-4 bg-primary-light border-bottom border-primary border-opacity-10">
<h5 class="fw-bold mb-0 text-primary">Order Summary</h5>
</div>
<div class="p-4 bg-white">
<div class="d-flex align-items-center mb-4 pb-4 border-bottom">
{% if book.cover_image %}
<img src="{{ book.cover_image.url }}" class="rounded-3 shadow-sm me-3" style="width: 80px; height: 110px; object-fit: cover;">
{% else %}
<div class="rounded-3 bg-light me-3 d-flex align-items-center justify-content-center" style="width: 80px; height: 110px;">
<i class="fas fa-book text-muted opacity-25"></i>
</div>
{% endif %}
<div>
<h6 class="fw-bold mb-1 text-dark">{{ book.title }}</h6>
<p class="small text-muted mb-0">{{ book.category.name }}</p>
<span class="badge bg-light text-primary mt-2 rounded-pill small">Digital PDF</span>
</div>
</div>
<div class="d-flex justify-content-between mb-2">
<span class="text-muted">Item Price</span>
<span class="fw-bold text-dark">${{ book.price }}</span>
</div>
<div class="d-flex justify-content-between mb-4">
<span class="text-muted">Transaction Fee</span>
<span class="text-success fw-bold">FREE</span>
</div>
<hr class="my-4 opacity-10">
<div class="d-flex justify-content-between align-items-center mb-0">
<h5 class="fw-800 mb-0">Total Amount</h5>
<h4 class="fw-800 text-primary mb-0">${{ book.price }}</h4>
</div>
</div>
<div class="p-4 bg-light text-center">
<p class="small text-muted mb-0"><i class="fas fa-lock me-2 text-primary"></i>Secure checkout provided by BookStore</p>
</div>
</div>
</div>
<!-- Checkout Form (Right) -->
<div class="col-lg-6 order-lg-1">
<div class="card border-0 shadow-soft rounded-4 p-4 p-md-5 bg-white">
<!-- Step 1: Payment Instructions -->
<div class="mb-5">
<div class="d-flex align-items-center mb-4">
<span class="bg-primary text-white rounded-circle d-flex align-items-center justify-content-center me-3 shadow-sm" style="width: 32px; height: 32px; font-size: 0.9rem; font-weight: 800;">1</span>
<h5 class="fw-bold mb-0">Payment Instructions</h5>
</div>
<div class="bg-primary-light p-4 rounded-4 mb-4 border border-primary border-opacity-10 position-relative overflow-hidden">
<div class="position-absolute top-0 end-0 p-3 opacity-10">
<i class="fas fa-mobile-screen-button fa-5x"></i>
</div>
<p class="small text-primary fw-bold mb-3 text-uppercase letter-spacing-1">Send your payment to:</p>
<div class="row g-3">
<div class="col-12">
<div class="payment-method-item bg-white p-3 rounded-3 shadow-sm d-flex align-items-center">
<div class="icon bg-success bg-opacity-10 text-success rounded-circle me-3 p-2">
<i class="fas fa-money-bill-wave"></i>
</div>
<div>
<small class="text-muted d-block" style="font-size: 0.7rem;">ZAAD / SAHAL / EVC PLUS</small>
<span class="fw-bold text-dark fs-5">+252 63 4844506</span>
</div>
</div>
</div>
</div>
<p class="small text-muted mt-4 mb-0">
<i class="fas fa-info-circle me-2 text-primary"></i>
After transfer, please keep your <strong>Transaction ID</strong> ready to enter below.
</p>
</div>
</div>
<!-- Step 2: Verification Details -->
<div>
<div class="d-flex align-items-center mb-4">
<span class="bg-primary text-white rounded-circle d-flex align-items-center justify-content-center me-3 shadow-sm" style="width: 32px; height: 32px; font-size: 0.9rem; font-weight: 800;">2</span>
<h5 class="fw-bold mb-0">Verification Details</h5>
</div>
<form action="{% url 'checkout' book.slug %}" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<div class="mb-4">
<label for="email" class="form-label fw-bold small text-muted text-uppercase">Email Address</label>
<div class="input-group">
<span class="input-group-text bg-light border-0 px-3"><i class="far fa-envelope text-muted"></i></span>
<input type="email" class="form-control bg-light border-0 py-3 px-4 shadow-none" name="email" required placeholder="Where should we send your book?">
</div>
<div id="emailHelp" class="form-text small text-muted mt-2">We'll never share your email with anyone else.</div>
</div>
<div class="mb-4">
<label for="transaction_id" class="form-label fw-bold small text-muted text-uppercase">Transaction ID / Reference</label>
<div class="input-group">
<span class="input-group-text bg-light border-0 px-3"><i class="fas fa-hashtag text-muted"></i></span>
<input type="text" class="form-control bg-light border-0 py-3 px-4 shadow-none" name="transaction_id" required placeholder="Enter the ID from your mobile transfer">
</div>
</div>
<div class="mb-5">
<label for="screenshot" class="form-label fw-bold small text-muted text-uppercase">Payment Screenshot (Optional)</label>
<input type="file" class="form-control bg-light border-0 py-3 px-4 shadow-none" name="screenshot" accept="image/*">
<div class="form-text small text-muted mt-2">Adding a screenshot helps us verify your payment faster.</div>
</div>
<button type="submit" class="btn btn-primary btn-lg w-100 py-3 fw-bold rounded-pill shadow-lg mt-3">
Confirm Purchase & Submit
<i class="fas fa-arrow-right ms-2"></i>
</button>
</form>
</div>
<!-- Trust Badges -->
<div class="mt-5 pt-4 border-top">
<div class="row g-3 text-center">
<div class="col-4">
<i class="fas fa-shield-alt text-muted opacity-50 mb-2 fa-lg d-block"></i>
<span class="small text-muted opacity-75" style="font-size: 0.65rem; font-weight: bold; text-uppercase;">SECURE PAYMENT</span>
</div>
<div class="col-4 border-start border-end">
<i class="fas fa-bolt text-muted opacity-50 mb-2 fa-lg d-block"></i>
<span class="small text-muted opacity-75" style="font-size: 0.65rem; font-weight: bold; text-uppercase;">INSTANT ACCESS</span>
</div>
<div class="col-4">
<i class="fas fa-user-check text-muted opacity-50 mb-2 fa-lg d-block"></i>
<span class="small text-muted opacity-75" style="font-size: 0.65rem; font-weight: bold; text-uppercase;">VERIFIED SELLER</span>
</div>
</div>
</div>
<!-- Support -->
<div class="mt-4 text-center">
<p class="small text-muted">Need help? <a href="https://wa.me/252634844506" class="text-primary fw-bold text-decoration-none"><i class="fab fa-whatsapp me-1"></i>Contact support on WhatsApp</a></p>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,63 @@
{% extends "base.html" %}
{% block title %}Contact Us | Digital Bookstore{% endblock %}
{% block content %}
<header class="bg-white border-bottom py-5 mb-5">
<div class="container py-4">
<h1 class="fw-800 display-5 mb-0 text-center">Get in <span class="text-primary-gradient">Touch</span></h1>
<p class="text-muted fs-5 mt-2 text-center">We're here to help you with your digital book experience.</p>
</div>
</header>
<div class="container mb-5 pb-5">
<div class="row justify-content-center">
<div class="col-lg-6">
<div class="card border-0 shadow-soft rounded-4 p-5 bg-white text-center">
<div class="icon-box mb-4 mx-auto bg-primary-light text-primary rounded-circle d-flex align-items-center justify-content-center" style="width: 80px; height: 80px;">
<i class="fas fa-headset fa-2x"></i>
</div>
<h3 class="fw-bold mb-4">Support & Inquiries</h3>
<p class="text-muted mb-5">Have questions about a book or your order? Reach out to our team through any of the channels below.</p>
<div class="contact-methods text-start">
<div class="d-flex align-items-center mb-4 p-3 bg-light rounded-4">
<div class="flex-shrink-0 bg-white shadow-sm rounded-circle p-3 me-4 text-success">
<i class="fab fa-whatsapp fa-xl"></i>
</div>
<div>
<span class="d-block text-muted small fw-bold text-uppercase">WhatsApp Support</span>
<a href="https://wa.me/252634844506" class="text-dark fw-bold text-decoration-none fs-5">+252 63 4844506</a>
</div>
</div>
<div class="d-flex align-items-center mb-4 p-3 bg-light rounded-4">
<div class="flex-shrink-0 bg-white shadow-sm rounded-circle p-3 me-4 text-primary">
<i class="far fa-envelope fa-xl"></i>
</div>
<div>
<span class="d-block text-muted small fw-bold text-uppercase">Email Address</span>
<a href="mailto:support@bookstore.com" class="text-dark fw-bold text-decoration-none fs-5">support@bookstore.com</a>
</div>
</div>
<div class="d-flex align-items-center p-3 bg-light rounded-4">
<div class="flex-shrink-0 bg-white shadow-sm rounded-circle p-3 me-4 text-danger">
<i class="fas fa-location-dot fa-xl"></i>
</div>
<div>
<span class="d-block text-muted small fw-bold text-uppercase">Headquarters</span>
<span class="text-dark fw-bold fs-5">Hargeisa, Somalia</span>
</div>
</div>
</div>
<div class="mt-5 pt-4 border-top">
<a href="https://wa.me/252634844506" class="btn btn-primary btn-lg w-100 py-3 rounded-pill shadow-lg fw-bold">
<i class="fab fa-whatsapp me-2"></i> Chat with us Now
</a>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -1,145 +1,227 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load static %}
{% block title %}{{ project_name }}{% endblock %} {% block title %}Home | Digital Bookstore - Premium PDFs{% endblock %}
{% block head %}
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">
<style>
: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);
}
* {
box-sizing: border-box;
}
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;
}
body::before {
content: '';
position: absolute;
inset: 0;
background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='100' height='100' viewBox='0 0 100 100'><path d='M-10 10L110 10M10 -10L10 110' stroke-width='1' stroke='rgba(255,255,255,0.05)'/></svg>");
animation: bg-pan 20s linear infinite;
z-index: -1;
}
@keyframes bg-pan {
0% {
background-position: 0% 0%;
}
100% {
background-position: 100% 100%;
}
}
main {
padding: 2rem;
}
.card {
background: var(--card-bg-color);
border: 1px solid var(--card-border-color);
border-radius: 16px;
padding: 2.5rem 2rem;
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
box-shadow: 0 12px 36px rgba(0, 0, 0, 0.25);
}
h1 {
font-size: clamp(2.2rem, 3vw + 1.2rem, 3.2rem);
font-weight: 700;
margin: 0 0 1.2rem;
letter-spacing: -0.02em;
}
p {
margin: 0.5rem 0;
font-size: 1.1rem;
opacity: 0.92;
}
.loader {
margin: 1.5rem auto;
width: 56px;
height: 56px;
border: 4px solid rgba(255, 255, 255, 0.25);
border-top-color: #fff;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
.runtime code {
background: rgba(0, 0, 0, 0.25);
padding: 0.15rem 0.45rem;
border-radius: 4px;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;
}
footer {
position: absolute;
bottom: 1rem;
width: 100%;
text-align: center;
font-size: 0.85rem;
opacity: 0.75;
}
</style>
{% endblock %}
{% block content %} {% block content %}
<main> <!-- Hero Section -->
<div class="card"> <section class="hero-section py-5 mb-5 overflow-hidden position-relative">
<h1>Analyzing your requirements and generating your app…</h1> <div class="container py-lg-5">
<div class="loader" role="status" aria-live="polite" aria-label="Applying initial changes"> <div class="row align-items-center g-5">
<span class="sr-only">Loading…</span> <div class="col-lg-6 fade-in-up">
<span class="badge bg-primary-light text-primary px-3 py-2 rounded-pill fw-bold mb-3 d-inline-block">NEW ARRIVALS 2026</span>
<h1 class="display-3 fw-800 mb-4 lh-sm">
Find Your Next <span class="text-primary-gradient">Great Adventure</span> In A Book.
</h1>
<p class="lead text-muted mb-5 pe-lg-5 fs-5">
Explore our curated collection of high-quality digital books. From educational resources to classic literature, we have it all.
</p>
<div class="search-box-wrap d-flex mb-4 border align-items-center p-2 rounded-pill shadow-sm">
<form action="{% url 'book_list' %}" method="GET" class="d-flex flex-grow-1">
<i class="fas fa-search text-muted ms-3"></i>
<input type="text" name="q" class="form-control border-0 bg-transparent fs-6 shadow-none" placeholder="Search by title, author or category...">
<button class="btn btn-primary rounded-pill px-4 ms-2 d-none d-md-block">Search</button>
</form>
</div>
<div class="d-flex gap-4 align-items-center text-muted small mt-2 px-3">
<span><i class="fas fa-check-circle text-primary me-2"></i>Instant Download</span>
<span><i class="fas fa-check-circle text-primary me-2"></i>Secure Payment</span>
<span><i class="fas fa-check-circle text-primary me-2"></i>Premium Quality</span>
</div>
</div>
<div class="col-lg-6 d-none d-lg-block fade-in-up" style="animation-delay: 0.2s;">
<div class="hero-image-wrap position-relative">
<!-- Illustration or Image Placeholder -->
<div class="floating-shape shape-1"></div>
<div class="floating-shape shape-2"></div>
<div class="glass-card shadow-lg p-3 rounded-4 bg-white">
<img src="https://images.pexels.com/photos/159866/books-book-pages-read-literature-159866.jpeg?auto=compress&cs=tinysrgb&w=800" alt="Hero Books" class="img-fluid rounded-4 shadow-sm" style="min-height: 450px; object-fit: cover;">
</div>
</div>
</div>
</div>
</div> </div>
<p class="hint">AppWizzy AI is collecting your requirements and applying the first changes.</p> </section>
<p class="hint">This page will refresh automatically as the plan is implemented.</p>
<p class="runtime"> <!-- Categories Section -->
Runtime: Django <code>{{ django_version }}</code> · Python <code>{{ python_version }}</code> <section class="container mb-5 py-4">
— UTC <code>{{ current_time|date:"Y-m-d H:i:s" }}</code> <div class="d-flex justify-content-between align-items-center mb-5">
</p> <div>
</div> <h2 class="fw-bold mb-1">Browse Categories</h2>
</main> <p class="text-muted mb-0 small">Find books by your favorite genres</p>
<footer> </div>
Page updated: {{ current_time|date:"Y-m-d H:i:s" }} (UTC) <a href="{% url 'book_list' %}" class="btn btn-link text-decoration-none fw-bold text-primary hover-primary">
</footer> View All <i class="fas fa-arrow-right ms-2 small"></i>
</a>
</div>
<div class="row g-4">
{% for category in categories %}
<div class="col-md-3 col-6">
<a href="{% url 'book_list' %}?category={{ category.slug }}" class="text-decoration-none">
<div class="category-pill h-100 d-flex flex-column align-items-center justify-content-center">
<div class="icon-wrap bg-primary-light text-primary rounded-circle mb-3 d-flex align-items-center justify-content-center" style="width: 64px; height: 64px;">
{% if category.image %}
<img src="{{ category.image.url }}" class="img-fluid rounded-circle" style="width: 40px; height: 40px; object-fit: cover;">
{% else %}
<i class="fas fa-book-open fa-lg"></i>
{% endif %}
</div>
<h6 class="mb-0 text-dark fw-bold">{{ category.name }}</h6>
<span class="small text-muted mt-1">{{ category.books.count }} Books</span>
</div>
</a>
</div>
{% empty %}
<!-- Default Demo Categories if none exist -->
<div class="col-md-3 col-6">
<div class="category-pill bg-light border-0 opacity-50">
<i class="fas fa-graduation-cap fa-2x mb-3 text-muted"></i>
<h6 class="mb-0 text-muted">Educational</h6>
</div>
</div>
<div class="col-md-3 col-6">
<div class="category-pill bg-light border-0 opacity-50">
<i class="fas fa-feather fa-2x mb-3 text-muted"></i>
<h6 class="mb-0 text-muted">Literature</h6>
</div>
</div>
<div class="col-md-3 col-6">
<div class="category-pill bg-light border-0 opacity-50">
<i class="fas fa-history fa-2x mb-3 text-muted"></i>
<h6 class="mb-0 text-muted">History</h6>
</div>
</div>
<div class="col-md-3 col-6">
<div class="category-pill bg-light border-0 opacity-50">
<i class="fas fa-briefcase fa-2x mb-3 text-muted"></i>
<h6 class="mb-0 text-muted">Business</h6>
</div>
</div>
{% endfor %}
</div>
</section>
<!-- Featured Books -->
<section class="container mb-5 py-5">
<div class="text-center mb-5">
<h2 class="fw-bold mb-1">Featured Collections</h2>
<p class="text-muted mb-0">Our hand-picked selections for you</p>
</div>
<div class="row g-4 justify-content-center">
{% for book in featured_books %}
<div class="col-lg-3 col-md-6">
<div class="card book-card h-100">
<div class="position-relative">
{% if book.cover_image %}
<img src="{{ book.cover_image.url }}" class="card-img-top" alt="{{ book.title }}" style="height: 350px; object-fit: cover;">
{% else %}
<div class="card-img-top bg-light d-flex align-items-center justify-content-center" style="height: 350px;">
<i class="fas fa-book fa-3x text-muted opacity-25"></i>
</div>
{% endif %}
<div class="position-absolute top-0 end-0 m-3">
<span class="badge bg-white text-dark shadow-sm rounded-pill fw-bold px-3 py-2">${{ book.price }}</span>
</div>
</div>
<div class="card-body">
<p class="text-primary small fw-bold mb-2 text-uppercase letter-spacing-1">{{ book.category.name }}</p>
<h5 class="card-title fw-bold text-dark mb-3 line-clamp-2">{{ book.title }}</h5>
<div class="d-grid mt-4">
<a href="{% url 'book_detail' book.slug %}" class="btn btn-outline-dark rounded-pill">View Details</a>
</div>
</div>
</div>
</div>
{% empty %}
<div class="col-12 text-center py-5">
<div class="bg-light p-5 rounded-4 d-inline-block">
<i class="fas fa-books-medical fa-3x text-muted mb-4"></i>
<p class="lead text-muted">Our shelves are being stocked. Check back soon!</p>
<a href="/admin/core/book/add/" class="btn btn-primary rounded-pill px-4 mt-3">Add First Book</a>
</div>
</div>
{% endfor %}
</div>
</section>
<!-- Why Choose Us / Trust Badges -->
<section class="bg-light py-5 mt-5">
<div class="container">
<div class="row g-4 py-4 text-center">
<div class="col-md-4">
<div class="p-4">
<i class="fas fa-bolt fa-3x text-primary mb-4 opacity-75"></i>
<h5 class="fw-bold">Instant Access</h5>
<p class="text-muted small">Download your books immediately after payment confirmation. No waiting, no shipping.</p>
</div>
</div>
<div class="col-md-4">
<div class="p-4 border-start border-end border-opacity-10">
<i class="fas fa-shield-halved fa-3x text-primary mb-4 opacity-75"></i>
<h5 class="fw-bold">Secure Payment</h5>
<p class="text-muted small">We support EVC Plus, Zaad, and Sahal. Your transactions are safe and verified manually.</p>
</div>
</div>
<div class="col-md-4">
<div class="p-4">
<i class="fas fa-headset fa-3x text-primary mb-4 opacity-75"></i>
<h5 class="fw-bold">Premium Support</h5>
<p class="text-muted small">Need help with your download? Our team is available 24/7 to assist you via WhatsApp.</p>
</div>
</div>
</div>
</div>
</section>
<!-- AdSense Header Slot (Styled) -->
<div class="container mt-5">
<div class="adsense-slot rounded-4 border-0 bg-white shadow-sm p-5 text-center text-muted small">
<i class="fas fa-ad fa-lg mb-2 d-block"></i>
Sponsorship Space Available
</div>
</div>
<style>
.line-clamp-2 {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
.letter-spacing-1 {
letter-spacing: 1px;
}
.hero-image-wrap::before {
content: '';
position: absolute;
width: 100%;
height: 100%;
border: 2px solid var(--primary);
border-radius: 2rem;
top: 20px;
left: 20px;
z-index: -1;
opacity: 0.2;
}
.floating-shape {
position: absolute;
z-index: -1;
border-radius: 50%;
filter: blur(40px);
}
.shape-1 {
width: 200px;
height: 200px;
background: rgba(13, 110, 253, 0.1);
top: -50px;
right: -50px;
}
.shape-2 {
width: 150px;
height: 150px;
background: rgba(255, 159, 28, 0.05);
bottom: -30px;
left: -30px;
}
</style>
{% endblock %} {% endblock %}

View File

@ -0,0 +1,26 @@
{% extends "base.html" %}
{% block title %}Order Successful | Digital Bookstore{% endblock %}
{% block content %}
<div class="container py-5 text-center">
<div class="row justify-content-center">
<div class="col-md-6">
<div class="card shadow-lg p-5 mb-5 bg-white rounded border-0">
<h1 class="display-3 mb-4 text-success">Order Success!</h1>
<p class="lead mb-4">Thank you for your purchase. We have received your order and are currently verifying your payment.</p>
<div class="bg-light p-4 rounded mb-5 shadow-sm">
<h5>Next Steps:</h5>
<ul class="list-unstyled mb-0">
<li>1. Our team will verify your transaction ID.</li>
<li>2. Once verified, we will email you the download link.</li>
<li>3. Check your inbox and spam folder for the book.</li>
</ul>
</div>
<div class="text-center">
<a href="{% url 'home' %}" class="btn btn-primary btn-lg px-5 shadow-none">Back to Library</a>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,17 @@
{% extends "base.html" %}
{% block title %}Privacy Policy | Digital Bookstore{% endblock %}
{% block content %}
<div class="container py-5">
<div class="row justify-content-center">
<div class="col-md-8">
<h1 class="mb-4">Privacy Policy</h1>
<p class="lead">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.</p>
<h3 class="mt-5">Cookies & Ads</h3>
<p>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.</p>
<h3 class="mt-5">Data Protection</h3>
<p>We do not sell or share your personal data with third parties. All local payment transactions are processed through secure gateways.</p>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,18 @@
{% extends "base.html" %}
{% block title %}Terms & Conditions | Digital Bookstore{% endblock %}
{% block content %}
<div class="container py-5">
<div class="row justify-content-center">
<div class="col-md-8">
<h1 class="mb-4">Terms & Conditions</h1>
<p class="lead">Isticmaalka website-kan waxay ka dhigantahay inaad ku raacday shuruudaha soo socda:</p>
<ul class="list-group list-group-flush mb-5 shadow-sm rounded">
<li class="list-group-item">Buugaagta aad halkan ka iibsanayso ama ka soo dagsanayso waa isticmaalkaaga gaarka ah (Personal use only).</li>
<li class="list-group-item">Lama ogola in dib loo iibiyo ama loo qaybiyo buugaagta adiga oo aan oggolaansho ka helin maamulka.</li>
<li class="list-group-item">Lacagaha la bixiyo dib looma soo celiyo maadaama badeecadu tahay mid dhijitaal ah (Digital product).</li>
</ul>
</div>
</div>
</div>
{% endblock %}

View File

@ -1,7 +1,14 @@
from django.urls import path from django.urls import path
from . import views
from .views import home
urlpatterns = [ urlpatterns = [
path("", home, name="home"), path("", views.home, name="home"),
] path("books/", views.book_list, name="book_list"),
path("book/<slug:slug>/", views.book_detail, name="book_detail"),
path("book/<slug:slug>/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"),
]

View File

@ -1,25 +1,75 @@
import os from django.shortcuts import render, get_object_or_404, redirect
import platform from .models import Category, Book, Order
from django.db.models import Q
from django import get_version as django_version from django.contrib import messages
from django.shortcuts import render
from django.utils import timezone
def home(request): def home(request):
"""Render the landing screen with loader and environment details.""" featured_books = Book.objects.filter(is_featured=True)[:6]
host_name = request.get_host().lower() if not featured_books.exists():
agent_brand = "AppWizzy" if host_name == "appwizzy.com" else "Flatlogic" featured_books = Book.objects.all()[:6]
now = timezone.now() categories = Category.objects.all()
return render(request, "core/index.html", {
"featured_books": featured_books,
"categories": categories,
})
context = { def book_list(request):
"project_name": "New Style", query = request.GET.get('q')
"agent_brand": agent_brand, category_slug = request.GET.get('category')
"django_version": django_version(), books = Book.objects.all()
"python_version": platform.python_version(), categories = Category.objects.all()
"current_time": now,
"host_name": host_name, if query:
"project_description": os.getenv("PROJECT_DESCRIPTION", ""), books = books.filter(Q(title__icontains=query) | Q(description__icontains=query))
"project_image_url": os.getenv("PROJECT_IMAGE_URL", ""), if category_slug:
} books = books.filter(category__slug=category_slug)
return render(request, "core/index.html", context)
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")

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

BIN
media/payments/old-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

View File

@ -1,4 +1,186 @@
/* Custom styles for the application */ /* Global Styles */
body { :root {
font-family: system-ui, -apple-system, sans-serif; --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;
}