Spaces:
Sleeping
Sleeping
Upload 134 files
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- .dockerignore +10 -0
- .gitattributes +2 -0
- Dockerfile +23 -0
- MistryMart/Accounts/Home/__init__.py +0 -0
- MistryMart/Accounts/Home/__pycache__/__init__.cpython-313.pyc +0 -0
- MistryMart/Accounts/Home/__pycache__/admin.cpython-313.pyc +0 -0
- MistryMart/Accounts/Home/__pycache__/apps.cpython-313.pyc +0 -0
- MistryMart/Accounts/Home/__pycache__/models.cpython-313.pyc +0 -0
- MistryMart/Accounts/Home/__pycache__/urls.cpython-313.pyc +0 -0
- MistryMart/Accounts/Home/__pycache__/views.cpython-313.pyc +0 -0
- MistryMart/Accounts/Home/admin.py +3 -0
- MistryMart/Accounts/Home/apps.py +6 -0
- MistryMart/Accounts/Home/migrations/__init__.py +0 -0
- MistryMart/Accounts/Home/migrations/__pycache__/__init__.cpython-313.pyc +0 -0
- MistryMart/Accounts/Home/models.py +3 -0
- MistryMart/Accounts/Home/templates/index.html +247 -0
- MistryMart/Accounts/Home/tests.py +3 -0
- MistryMart/Accounts/Home/urls.py +11 -0
- MistryMart/Accounts/Home/views.py +12 -0
- MistryMart/Accounts/__init__.py +0 -0
- MistryMart/Accounts/__pycache__/__init__.cpython-313.pyc +0 -0
- MistryMart/Accounts/__pycache__/admin.cpython-313.pyc +0 -0
- MistryMart/Accounts/__pycache__/apps.cpython-313.pyc +0 -0
- MistryMart/Accounts/__pycache__/models.cpython-313.pyc +0 -0
- MistryMart/Accounts/__pycache__/urls.cpython-313.pyc +0 -0
- MistryMart/Accounts/__pycache__/views.cpython-313.pyc +0 -0
- MistryMart/Accounts/admin.py +36 -0
- MistryMart/Accounts/apps.py +6 -0
- MistryMart/Accounts/migrations/0001_initial.py +49 -0
- MistryMart/Accounts/migrations/__init__.py +0 -0
- MistryMart/Accounts/migrations/__pycache__/0001_initial.cpython-313.pyc +0 -0
- MistryMart/Accounts/migrations/__pycache__/__init__.cpython-313.pyc +0 -0
- MistryMart/Accounts/models.py +58 -0
- MistryMart/Accounts/templates/login.html +188 -0
- MistryMart/Accounts/templates/signup.html +211 -0
- MistryMart/Accounts/tests.py +3 -0
- MistryMart/Accounts/urls.py +12 -0
- MistryMart/Accounts/views.py +58 -0
- MistryMart/Analytics/__init__.py +0 -0
- MistryMart/Analytics/__pycache__/__init__.cpython-313.pyc +0 -0
- MistryMart/Analytics/__pycache__/admin.cpython-313.pyc +0 -0
- MistryMart/Analytics/__pycache__/apps.cpython-313.pyc +0 -0
- MistryMart/Analytics/__pycache__/models.cpython-313.pyc +0 -0
- MistryMart/Analytics/admin.py +17 -0
- MistryMart/Analytics/apps.py +6 -0
- MistryMart/Analytics/migrations/0001_initial.py +37 -0
- MistryMart/Analytics/migrations/__init__.py +0 -0
- MistryMart/Analytics/migrations/__pycache__/0001_initial.cpython-313.pyc +0 -0
- MistryMart/Analytics/migrations/__pycache__/__init__.cpython-313.pyc +0 -0
- MistryMart/Analytics/models.py +22 -0
.dockerignore
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
.git
|
| 2 |
+
.gitignore
|
| 3 |
+
.vscode
|
| 4 |
+
__pycache__
|
| 5 |
+
*.pyc
|
| 6 |
+
*.sqlite3
|
| 7 |
+
/static
|
| 8 |
+
/media
|
| 9 |
+
/venv
|
| 10 |
+
/env
|
.gitattributes
CHANGED
|
@@ -33,3 +33,5 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
MistryMart/db.sqlite3 filter=lfs diff=lfs merge=lfs -text
|
| 37 |
+
MistryMart/static/images/WhatsApp_Image_2025-08-16_at_10.06.25_PM.jpeg filter=lfs diff=lfs merge=lfs -text
|
Dockerfile
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Use an official Python runtime as a parent image
|
| 2 |
+
FROM python:3.11-slim
|
| 3 |
+
|
| 4 |
+
# Set environment variables
|
| 5 |
+
ENV PYTHONDONTWRITEBYTECODE 1
|
| 6 |
+
ENV PYTHONUNBUFFERED 1
|
| 7 |
+
|
| 8 |
+
# Set the working directory in the container
|
| 9 |
+
WORKDIR /usr/src/app
|
| 10 |
+
|
| 11 |
+
# Copy the current directory contents into the container at /usr/src/app
|
| 12 |
+
COPY . /usr/src/app/
|
| 13 |
+
|
| 14 |
+
# Install any needed packages specified in requirements.txt
|
| 15 |
+
RUN pip install --no-cache-dir -r requirements.txt
|
| 16 |
+
|
| 17 |
+
# Expose port 8000 for the Django development server
|
| 18 |
+
EXPOSE 8000
|
| 19 |
+
|
| 20 |
+
# Run the application
|
| 21 |
+
# Use the entrypoint to run migrations and then start the server
|
| 22 |
+
# Note: In a production environment, you would use a production-ready server like Gunicorn or uWSGI
|
| 23 |
+
CMD ["sh", "-c", "python manage.py migrate && python manage.py runserver 0.0.0.0:8000"]
|
MistryMart/Accounts/Home/__init__.py
ADDED
|
File without changes
|
MistryMart/Accounts/Home/__pycache__/__init__.cpython-313.pyc
ADDED
|
Binary file (138 Bytes). View file
|
|
|
MistryMart/Accounts/Home/__pycache__/admin.cpython-313.pyc
ADDED
|
Binary file (182 Bytes). View file
|
|
|
MistryMart/Accounts/Home/__pycache__/apps.cpython-313.pyc
ADDED
|
Binary file (498 Bytes). View file
|
|
|
MistryMart/Accounts/Home/__pycache__/models.cpython-313.pyc
ADDED
|
Binary file (179 Bytes). View file
|
|
|
MistryMart/Accounts/Home/__pycache__/urls.cpython-313.pyc
ADDED
|
Binary file (505 Bytes). View file
|
|
|
MistryMart/Accounts/Home/__pycache__/views.cpython-313.pyc
ADDED
|
Binary file (590 Bytes). View file
|
|
|
MistryMart/Accounts/Home/admin.py
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from django.contrib import admin
|
| 2 |
+
|
| 3 |
+
# Register your models here.
|
MistryMart/Accounts/Home/apps.py
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from django.apps import AppConfig
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
class HomeConfig(AppConfig):
|
| 5 |
+
default_auto_field = 'django.db.models.BigAutoField'
|
| 6 |
+
name = 'Home'
|
MistryMart/Accounts/Home/migrations/__init__.py
ADDED
|
File without changes
|
MistryMart/Accounts/Home/migrations/__pycache__/__init__.cpython-313.pyc
ADDED
|
Binary file (149 Bytes). View file
|
|
|
MistryMart/Accounts/Home/models.py
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from django.db import models
|
| 2 |
+
|
| 3 |
+
# Create your models here.
|
MistryMart/Accounts/Home/templates/index.html
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>MysteryBox | Home</title>
|
| 7 |
+
|
| 8 |
+
<script src="https://cdn.tailwindcss.com"></script>
|
| 9 |
+
</head>
|
| 10 |
+
<body class="bg-gray-50 text-gray-800">
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
<!-- Navbar -->
|
| 14 |
+
<header class="bg-purple-700 text-white">
|
| 15 |
+
<div class="max-w-7xl mx-auto flex justify-between items-center py-4 px-6">
|
| 16 |
+
|
| 17 |
+
<!-- Logo -->
|
| 18 |
+
<a href="/" class="text-xl font-bold tracking-wide">
|
| 19 |
+
🎁 MysteryBox
|
| 20 |
+
</a>
|
| 21 |
+
|
| 22 |
+
<!-- Navigation Links (Desktop) -->
|
| 23 |
+
<nav class="hidden md:flex space-x-6 text-sm font-medium">
|
| 24 |
+
<a href="/" class="hover:text-yellow-300">Home</a>
|
| 25 |
+
<a href="/boxes" class="hover:text-yellow-300">All Boxes</a>
|
| 26 |
+
<a href="/boxes/?category=gadgets" class="hover:text-yellow-300">electronics</a>
|
| 27 |
+
<a href="/boxes/?category=clothes" class="hover:text-yellow-300">Clothes</a>
|
| 28 |
+
<a href="/boxes/?category=accessories" class="hover:text-yellow-300">Accessories</a>
|
| 29 |
+
|
| 30 |
+
<a href="reward" class="hover:text-yellow-300">Rewards</a>
|
| 31 |
+
</nav>
|
| 32 |
+
|
| 33 |
+
<!-- Right Icons -->
|
| 34 |
+
<div class="flex items-center space-x-4">
|
| 35 |
+
<!-- Search -->
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
<!-- Cart -->
|
| 39 |
+
<a href="/cart/" class="relative">
|
| 40 |
+
<span class="text-xl">🛒</span>
|
| 41 |
+
<span class="absolute -top-2 -right-2 bg-yellow-400 text-black text-xs font-bold px-1 rounded">3</span>
|
| 42 |
+
</a>
|
| 43 |
+
|
| 44 |
+
<!-- Account -->
|
| 45 |
+
<a href="/Accounts/" class="hover:text-yellow-300">
|
| 46 |
+
{% if request.user.is_authenticated %}
|
| 47 |
+
<span>👤 Hello,{{ request.user.first_name|slice:"0:8" }}</span>
|
| 48 |
+
{% else %}
|
| 49 |
+
👤 Account
|
| 50 |
+
{% endif %}
|
| 51 |
+
</a>
|
| 52 |
+
{% if request.user.is_authenticated %}
|
| 53 |
+
<a href="Accounts/logout" class="hover:text-yellow-300">
|
| 54 |
+
|
| 55 |
+
👤 Logout
|
| 56 |
+
</a>
|
| 57 |
+
{% else %}
|
| 58 |
+
<a href="Accounts/login" class="hover:text-yellow-300">
|
| 59 |
+
👤 Login
|
| 60 |
+
</a>
|
| 61 |
+
{% endif %}
|
| 62 |
+
|
| 63 |
+
</div>
|
| 64 |
+
|
| 65 |
+
</div>
|
| 66 |
+
</header>
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
<!-- Hero Section -->
|
| 70 |
+
<section class="bg-gradient-to-r from-purple-700 to-purple-500 text-white py-20">
|
| 71 |
+
<div class="max-w-4xl mx-auto text-center">
|
| 72 |
+
<!-- Search Bar -->
|
| 73 |
+
<form action="/search/" method="get" class="mb-8">
|
| 74 |
+
<input type="text"
|
| 75 |
+
name="q"
|
| 76 |
+
placeholder="Search..."
|
| 77 |
+
class="w-full max-w-2xl px-5 py-2.5 rounded-full text-black text-base focus:outline-none focus:ring-4 focus:ring-yellow-300 shadow" />
|
| 78 |
+
</form>
|
| 79 |
+
|
| 80 |
+
<h1 class="text-4xl md:text-6xl font-bold mb-4">
|
| 81 |
+
Unbox the Mystery. Discover the Surprise!
|
| 82 |
+
</h1>
|
| 83 |
+
<p class="text-xl mb-6">
|
| 84 |
+
Branded products at unbelievable prices — delivered to your door.
|
| 85 |
+
</p>
|
| 86 |
+
<a href="#boxes"
|
| 87 |
+
class="px-8 py-4 rounded-full bg-yellow-400 text-black font-semibold shadow-lg hover:bg-yellow-500 transition">
|
| 88 |
+
Shop Now
|
| 89 |
+
</a>
|
| 90 |
+
</div>
|
| 91 |
+
</section>
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
<!-- Mystery Boxes -->
|
| 95 |
+
<section id="boxes" class="py-16 max-w-6xl mx-auto grid grid-cols-1 md:grid-cols-3 gap-6 text-center">
|
| 96 |
+
<div class="p-6 rounded-lg bg-orange-400 text-white shadow-lg">
|
| 97 |
+
<h2 class="text-2xl font-bold mb-4">₹299 Box</h2>
|
| 98 |
+
<a href="#" class="px-4 py-2 rounded-full bg-white text-black font-semibold">Buy Now</a>
|
| 99 |
+
</div>
|
| 100 |
+
<div class="p-6 rounded-lg bg-yellow-400 text-black shadow-lg">
|
| 101 |
+
<h2 class="text-2xl font-bold mb-4">₹499 Box</h2>
|
| 102 |
+
<a href="#" class="px-4 py-2 rounded-full bg-black text-white font-semibold">Buy Now</a>
|
| 103 |
+
</div>
|
| 104 |
+
<div class="p-6 rounded-lg bg-blue-500 text-white shadow-lg">
|
| 105 |
+
<h2 class="text-2xl font-bold mb-4">₹999 Box</h2>
|
| 106 |
+
<a href="#" class="px-4 py-2 rounded-full bg-white text-black font-semibold">Buy Now</a>
|
| 107 |
+
</div>
|
| 108 |
+
</section>
|
| 109 |
+
<main class="max-w-7xl mx-auto px-6 py-10">
|
| 110 |
+
|
| 111 |
+
<!-- Grid of Boxes -->
|
| 112 |
+
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-4 gap-8">
|
| 113 |
+
|
| 114 |
+
<!-- Example Box Item -->
|
| 115 |
+
<div class="bg-white shadow-lg rounded-lg overflow-hidden hover:scale-105 transition">
|
| 116 |
+
<img src="https://em-content.zobj.net/source/microsoft-teams/337/wrapped-gift_1f381.png" alt="Box" class="w-full h-40 object-contain bg-gray-200 p-6">
|
| 117 |
+
<div class="p-4 text-center">
|
| 118 |
+
<h2 class="text-lg font-bold">Box ₹299</h2>
|
| 119 |
+
<p class="text-gray-500 text-sm">Small Mystery Surprise</p>
|
| 120 |
+
<button class="mt-4 px-4 py-2 bg-purple-700 text-white rounded hover:bg-purple-800">Buy Now</button>
|
| 121 |
+
</div>
|
| 122 |
+
</div>
|
| 123 |
+
|
| 124 |
+
<div class="bg-white shadow-lg rounded-lg overflow-hidden hover:scale-105 transition">
|
| 125 |
+
<img src="https://em-content.zobj.net/source/microsoft-teams/337/wrapped-gift_1f381.png" alt="Box" class="w-full h-40 object-contain bg-gray-200 p-6">
|
| 126 |
+
<div class="p-4 text-center">
|
| 127 |
+
<h2 class="text-lg font-bold">Box ₹499</h2>
|
| 128 |
+
<p class="text-gray-500 text-sm">Medium Mystery Box</p>
|
| 129 |
+
<button class="mt-4 px-4 py-2 bg-purple-700 text-white rounded hover:bg-purple-800">Buy Now</button>
|
| 130 |
+
</div>
|
| 131 |
+
</div>
|
| 132 |
+
|
| 133 |
+
<div class="bg-white shadow-lg rounded-lg overflow-hidden hover:scale-105 transition">
|
| 134 |
+
<img src="https://em-content.zobj.net/source/microsoft-teams/337/wrapped-gift_1f381.png" alt="Box" class="w-full h-40 object-contain bg-gray-200 p-6">
|
| 135 |
+
<div class="p-4 text-center">
|
| 136 |
+
<h2 class="text-lg font-bold">Box ₹999</h2>
|
| 137 |
+
<p class="text-gray-500 text-sm">Premium Mystery Offer</p>
|
| 138 |
+
<button class="mt-4 px-4 py-2 bg-purple-700 text-white rounded hover:bg-purple-800">Buy Now</button>
|
| 139 |
+
</div>
|
| 140 |
+
</div>
|
| 141 |
+
|
| 142 |
+
<div class="bg-white shadow-lg rounded-lg overflow-hidden hover:scale-105 transition">
|
| 143 |
+
<img src="https://em-content.zobj.net/source/microsoft-teams/337/wrapped-gift_1f381.png" alt="Box" class="w-full h-40 object-contain bg-gray-200 p-6">
|
| 144 |
+
<div class="p-4 text-center">
|
| 145 |
+
<h2 class="text-lg font-bold">Box ₹1499</h2>
|
| 146 |
+
<p class="text-gray-500 text-sm">Ultra Luxury Box</p>
|
| 147 |
+
<button class="mt-4 px-4 py-2 bg-purple-700 text-white rounded hover:bg-purple-800">Buy Now</button>
|
| 148 |
+
</div>
|
| 149 |
+
</div>
|
| 150 |
+
<!-- 3rd row (add more if needed) -->
|
| 151 |
+
|
| 152 |
+
|
| 153 |
+
</div>
|
| 154 |
+
</main>
|
| 155 |
+
<!-- Features -->
|
| 156 |
+
<section class="bg-white py-16">
|
| 157 |
+
<div class="max-w-6xl mx-auto text-center">
|
| 158 |
+
<h2 class="text-3xl font-bold mb-8">Why Choose Us</h2>
|
| 159 |
+
<div class="grid grid-cols-2 md:grid-cols-4 gap-8">
|
| 160 |
+
<div>
|
| 161 |
+
<div class="text-4xl">💰</div>
|
| 162 |
+
<p class="mt-2">Affordable Prices</p>
|
| 163 |
+
</div>
|
| 164 |
+
<div>
|
| 165 |
+
<div class="text-4xl">🎉</div>
|
| 166 |
+
<p class="mt-2">Surprise & Fun</p>
|
| 167 |
+
</div>
|
| 168 |
+
<div>
|
| 169 |
+
<div class="text-4xl">🌱</div>
|
| 170 |
+
<p class="mt-2">Eco-Friendly</p>
|
| 171 |
+
</div>
|
| 172 |
+
<div>
|
| 173 |
+
<div class="text-4xl">⭐</div>
|
| 174 |
+
<p class="mt-2">Trusted Sellers</p>
|
| 175 |
+
</div>
|
| 176 |
+
</div>
|
| 177 |
+
</div>
|
| 178 |
+
</section>
|
| 179 |
+
|
| 180 |
+
<!-- Reviews -->
|
| 181 |
+
<section class="py-16 bg-gray-100">
|
| 182 |
+
<div class="max-w-6xl mx-auto text-center">
|
| 183 |
+
<h2 class="text-3xl font-bold mb-8">Customer Reviews</h2>
|
| 184 |
+
<div class="grid md:grid-cols-2 gap-8">
|
| 185 |
+
<div class="p-6 bg-white rounded-lg shadow">
|
| 186 |
+
<strong class="block mb-2">😊 Aman</strong>
|
| 187 |
+
<p>“Loved the mystery box! Amazing quality at low cost.”</p>
|
| 188 |
+
<p class="mt-2 text-yellow-500">⭐⭐⭐⭐⭐</p>
|
| 189 |
+
</div>
|
| 190 |
+
<div class="p-6 bg-white rounded-lg shadow">
|
| 191 |
+
<strong class="block mb-2">😎 Lucky</strong>
|
| 192 |
+
<p>“Great surprise and value. Will order again!”</p>
|
| 193 |
+
<p class="mt-2 text-yellow-500">⭐⭐⭐⭐</p>
|
| 194 |
+
</div>
|
| 195 |
+
</div>
|
| 196 |
+
</div>
|
| 197 |
+
</section>
|
| 198 |
+
|
| 199 |
+
|
| 200 |
+
<!-- Footer -->
|
| 201 |
+
<footer class="bg-purple-700 text-white py-8">
|
| 202 |
+
<div class="max-w-6xl mx-auto px-4">
|
| 203 |
+
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 text-center md:text-left">
|
| 204 |
+
|
| 205 |
+
<!-- Logo & Tagline -->
|
| 206 |
+
<div>
|
| 207 |
+
<h2 class="text-lg font-bold">🎁 MysteryBox</h2>
|
| 208 |
+
<p class="text-sm mt-2">Affordable. Fun. Eco-Friendly.</p>
|
| 209 |
+
</div>
|
| 210 |
+
|
| 211 |
+
<!-- Navigation Links -->
|
| 212 |
+
<div>
|
| 213 |
+
<h3 class="font-semibold mb-3">Quick Links</h3>
|
| 214 |
+
<ul class="space-y-2">
|
| 215 |
+
<li><a href="/about" class="hover:underline">About Us</a></li>
|
| 216 |
+
<li><a href="/contact" class="hover:underline">Contact</a></li>
|
| 217 |
+
<li><a href="/faq" class="hover:underline">FAQ</a></li>
|
| 218 |
+
</ul>
|
| 219 |
+
</div>
|
| 220 |
+
|
| 221 |
+
<!-- Social Media -->
|
| 222 |
+
<div>
|
| 223 |
+
<h3 class="font-semibold mb-3">Follow Us</h3>
|
| 224 |
+
<div class="flex justify-center md:justify-start space-x-4 text-2xl">
|
| 225 |
+
<a href="https://instagram.com" target="_blank" class="hover:text-pink-400">
|
| 226 |
+
<i class="fab fa-instagram"></i>
|
| 227 |
+
</a>
|
| 228 |
+
<a href="https://facebook.com" target="_blank" class="hover:text-blue-400">
|
| 229 |
+
<i class="fab fa-facebook"></i>
|
| 230 |
+
</a>
|
| 231 |
+
</div>
|
| 232 |
+
</div>
|
| 233 |
+
</div>
|
| 234 |
+
|
| 235 |
+
<!-- Divider -->
|
| 236 |
+
<div class="border-t border-purple-500 mt-6 pt-4 text-center text-sm">
|
| 237 |
+
<p>© 2024 MysteryBox. All rights reserved.</p>
|
| 238 |
+
</div>
|
| 239 |
+
</div>
|
| 240 |
+
</footer>
|
| 241 |
+
|
| 242 |
+
<!-- ✅ Font Awesome (for social icons) -->
|
| 243 |
+
<script src="https://kit.fontawesome.com/3b5fbf8a70.js" crossorigin="anonymous"></script>
|
| 244 |
+
|
| 245 |
+
|
| 246 |
+
</body>
|
| 247 |
+
</html>
|
MistryMart/Accounts/Home/tests.py
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from django.test import TestCase
|
| 2 |
+
|
| 3 |
+
# Create your tests here.
|
MistryMart/Accounts/Home/urls.py
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from django.contrib import admin
|
| 2 |
+
from django.urls import path
|
| 3 |
+
from Home import views
|
| 4 |
+
from django.contrib.auth import views as auth_views
|
| 5 |
+
from . import *
|
| 6 |
+
|
| 7 |
+
urlpatterns = [
|
| 8 |
+
path("", views.index , name="Home"),
|
| 9 |
+
path("reward", views.all_boxes , name="box"),
|
| 10 |
+
|
| 11 |
+
]
|
MistryMart/Accounts/Home/views.py
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from django.shortcuts import render
|
| 2 |
+
from django.shortcuts import render , HttpResponse , redirect
|
| 3 |
+
# Create your views here.
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
def index(request):
|
| 8 |
+
return render(request, 'Home/templates/index.html' )
|
| 9 |
+
|
| 10 |
+
def all_boxes(request):
|
| 11 |
+
|
| 12 |
+
return render(request, "Boxes/templates/spin_wheel.html")
|
MistryMart/Accounts/__init__.py
ADDED
|
File without changes
|
MistryMart/Accounts/__pycache__/__init__.cpython-313.pyc
ADDED
|
Binary file (142 Bytes). View file
|
|
|
MistryMart/Accounts/__pycache__/admin.cpython-313.pyc
ADDED
|
Binary file (1.64 kB). View file
|
|
|
MistryMart/Accounts/__pycache__/apps.cpython-313.pyc
ADDED
|
Binary file (510 Bytes). View file
|
|
|
MistryMart/Accounts/__pycache__/models.cpython-313.pyc
ADDED
|
Binary file (3.7 kB). View file
|
|
|
MistryMart/Accounts/__pycache__/urls.cpython-313.pyc
ADDED
|
Binary file (579 Bytes). View file
|
|
|
MistryMart/Accounts/__pycache__/views.cpython-313.pyc
ADDED
|
Binary file (2.6 kB). View file
|
|
|
MistryMart/Accounts/admin.py
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from django.contrib import admin
|
| 2 |
+
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
|
| 3 |
+
from .models import User, Profile
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
class UserAdmin(BaseUserAdmin):
|
| 7 |
+
|
| 8 |
+
list_display = ('email', 'first_name', 'last_name', 'is_staff', 'is_active', 'date_joined')
|
| 9 |
+
list_filter = ('is_staff', 'is_active', 'is_superuser')
|
| 10 |
+
search_fields = ('email', 'first_name', 'last_name')
|
| 11 |
+
ordering = ('-date_joined',)
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
fieldsets = (
|
| 15 |
+
(None, {'fields': ('email', 'password')}),
|
| 16 |
+
('Personal Info', {'fields': ('first_name', 'last_name')}),
|
| 17 |
+
('Permissions', {'fields': ('is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions')}),
|
| 18 |
+
('Important dates', {'fields': ('last_login', 'date_joined')}),
|
| 19 |
+
)
|
| 20 |
+
|
| 21 |
+
add_fieldsets = (
|
| 22 |
+
(None, {
|
| 23 |
+
'classes': ('wide',),
|
| 24 |
+
'fields': ('email', 'password1', 'password2', 'is_active', 'is_staff')}
|
| 25 |
+
),
|
| 26 |
+
)
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
class ProfileAdmin(admin.ModelAdmin):
|
| 30 |
+
list_display = ('user', 'phone', 'wallet_balance')
|
| 31 |
+
search_fields = ('user__email', 'phone')
|
| 32 |
+
list_filter = ('wallet_balance',)
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
admin.site.register(User, UserAdmin)
|
| 36 |
+
admin.site.register(Profile, ProfileAdmin)
|
MistryMart/Accounts/apps.py
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from django.apps import AppConfig
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
class AccountsConfig(AppConfig):
|
| 5 |
+
default_auto_field = 'django.db.models.BigAutoField'
|
| 6 |
+
name = 'Accounts'
|
MistryMart/Accounts/migrations/0001_initial.py
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Generated by Django 5.2.4 on 2025-08-18 10:37
|
| 2 |
+
|
| 3 |
+
import django.db.models.deletion
|
| 4 |
+
import django.utils.timezone
|
| 5 |
+
from django.conf import settings
|
| 6 |
+
from django.db import migrations, models
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
class Migration(migrations.Migration):
|
| 10 |
+
|
| 11 |
+
initial = True
|
| 12 |
+
|
| 13 |
+
dependencies = [
|
| 14 |
+
('auth', '0012_alter_user_first_name_max_length'),
|
| 15 |
+
]
|
| 16 |
+
|
| 17 |
+
operations = [
|
| 18 |
+
migrations.CreateModel(
|
| 19 |
+
name='User',
|
| 20 |
+
fields=[
|
| 21 |
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
| 22 |
+
('password', models.CharField(max_length=128, verbose_name='password')),
|
| 23 |
+
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
|
| 24 |
+
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
|
| 25 |
+
('email', models.EmailField(max_length=255, unique=True)),
|
| 26 |
+
('first_name', models.CharField(blank=True, max_length=50, null=True)),
|
| 27 |
+
('last_name', models.CharField(blank=True, max_length=50, null=True)),
|
| 28 |
+
('is_active', models.BooleanField(default=True)),
|
| 29 |
+
('is_staff', models.BooleanField(default=False)),
|
| 30 |
+
('date_joined', models.DateTimeField(default=django.utils.timezone.now)),
|
| 31 |
+
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.group', verbose_name='groups')),
|
| 32 |
+
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions')),
|
| 33 |
+
],
|
| 34 |
+
options={
|
| 35 |
+
'abstract': False,
|
| 36 |
+
},
|
| 37 |
+
),
|
| 38 |
+
migrations.CreateModel(
|
| 39 |
+
name='Profile',
|
| 40 |
+
fields=[
|
| 41 |
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
| 42 |
+
('phone', models.CharField(blank=True, max_length=15, null=True)),
|
| 43 |
+
('address', models.TextField(blank=True, null=True)),
|
| 44 |
+
('wallet_balance', models.DecimalField(decimal_places=2, default=0.0, max_digits=10)),
|
| 45 |
+
('preferences', models.JSONField(blank=True, null=True)),
|
| 46 |
+
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='profile', to=settings.AUTH_USER_MODEL)),
|
| 47 |
+
],
|
| 48 |
+
),
|
| 49 |
+
]
|
MistryMart/Accounts/migrations/__init__.py
ADDED
|
File without changes
|
MistryMart/Accounts/migrations/__pycache__/0001_initial.cpython-313.pyc
ADDED
|
Binary file (3.36 kB). View file
|
|
|
MistryMart/Accounts/migrations/__pycache__/__init__.cpython-313.pyc
ADDED
|
Binary file (153 Bytes). View file
|
|
|
MistryMart/Accounts/models.py
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from django.db import models
|
| 2 |
+
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
|
| 3 |
+
from django.utils import timezone
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
# ---------------- CUSTOM USER MANAGER ----------------
|
| 7 |
+
class CustomUserManager(BaseUserManager):
|
| 8 |
+
def create_user(self, email, password=None, **extra_fields):
|
| 9 |
+
if not email:
|
| 10 |
+
raise ValueError("The Email field must be set")
|
| 11 |
+
email = self.normalize_email(email)
|
| 12 |
+
user = self.model(email=email, **extra_fields)
|
| 13 |
+
user.set_password(password)
|
| 14 |
+
user.save(using=self._db)
|
| 15 |
+
return user
|
| 16 |
+
|
| 17 |
+
def create_superuser(self, email, password=None, **extra_fields):
|
| 18 |
+
extra_fields.setdefault("is_staff", True)
|
| 19 |
+
extra_fields.setdefault("is_superuser", True)
|
| 20 |
+
|
| 21 |
+
if extra_fields.get("is_staff") is not True:
|
| 22 |
+
raise ValueError("Superuser must have is_staff=True.")
|
| 23 |
+
if extra_fields.get("is_superuser") is not True:
|
| 24 |
+
raise ValueError("Superuser must have is_superuser=True.")
|
| 25 |
+
|
| 26 |
+
return self.create_user(email, password, **extra_fields)
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
# ---------------- CUSTOM USER MODEL ----------------
|
| 30 |
+
class User(AbstractBaseUser, PermissionsMixin):
|
| 31 |
+
email = models.EmailField(unique=True, max_length=255)
|
| 32 |
+
first_name = models.CharField(max_length=50, blank=True, null=True)
|
| 33 |
+
last_name = models.CharField(max_length=50, blank=True, null=True)
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
is_active = models.BooleanField(default=True)
|
| 37 |
+
is_staff = models.BooleanField(default=False)
|
| 38 |
+
date_joined = models.DateTimeField(default=timezone.now)
|
| 39 |
+
|
| 40 |
+
objects = CustomUserManager()
|
| 41 |
+
|
| 42 |
+
USERNAME_FIELD = "email"
|
| 43 |
+
REQUIRED_FIELDS = []
|
| 44 |
+
|
| 45 |
+
def __str__(self):
|
| 46 |
+
return self.email
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
# ---------------- USER PROFILE MODEL ----------------
|
| 50 |
+
class Profile(models.Model):
|
| 51 |
+
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="profile")
|
| 52 |
+
phone = models.CharField(max_length=15, blank=True, null=True)
|
| 53 |
+
address = models.TextField(blank=True, null=True)
|
| 54 |
+
wallet_balance = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
|
| 55 |
+
preferences = models.JSONField(blank=True, null=True)
|
| 56 |
+
|
| 57 |
+
def __str__(self):
|
| 58 |
+
return f"Profile - {self.user.email}"
|
MistryMart/Accounts/templates/login.html
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>MysteryBox - Login</title>
|
| 7 |
+
<script src="https://cdn.tailwindcss.com"></script>
|
| 8 |
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
| 9 |
+
<script>
|
| 10 |
+
tailwind.config = {
|
| 11 |
+
theme: {
|
| 12 |
+
extend: {
|
| 13 |
+
animation: {
|
| 14 |
+
'float': 'float 6s ease-in-out infinite',
|
| 15 |
+
'pulse-slow': 'pulse 4s cubic-bezier(0.4, 0, 0.6, 1) infinite',
|
| 16 |
+
},
|
| 17 |
+
keyframes: {
|
| 18 |
+
float: {
|
| 19 |
+
'0%, 100%': { transform: 'translateY(0)' },
|
| 20 |
+
'50%': { transform: 'translateY(-10px)' },
|
| 21 |
+
}
|
| 22 |
+
}
|
| 23 |
+
}
|
| 24 |
+
}
|
| 25 |
+
}
|
| 26 |
+
</script>
|
| 27 |
+
<style>
|
| 28 |
+
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap');
|
| 29 |
+
|
| 30 |
+
body {
|
| 31 |
+
font-family: 'Poppins', sans-serif;
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
.mystery-bg {
|
| 35 |
+
background: linear-gradient(135deg, #8B5CF6 0%, #7C3AED 100%);
|
| 36 |
+
position: relative;
|
| 37 |
+
overflow: hidden;
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
.mystery-bg::before {
|
| 41 |
+
content: "";
|
| 42 |
+
position: absolute;
|
| 43 |
+
width: 200%;
|
| 44 |
+
height: 200%;
|
| 45 |
+
top: -50%;
|
| 46 |
+
left: -50%;
|
| 47 |
+
z-index: 0;
|
| 48 |
+
background: radial-gradient(circle, rgba(255,255,255,0.1) 10%, transparent 10.5%);
|
| 49 |
+
background-size: 20px 20px;
|
| 50 |
+
transform: rotate(30deg);
|
| 51 |
+
animation: pulse-slow 8s infinite;
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
.confetti {
|
| 55 |
+
position: absolute;
|
| 56 |
+
width: 10px;
|
| 57 |
+
height: 10px;
|
| 58 |
+
background-color: rgba(255, 255, 255, 0.5);
|
| 59 |
+
opacity: 0;
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
.btn-glow:hover {
|
| 63 |
+
box-shadow: 0 0 15px rgba(139, 92, 246, 0.6);
|
| 64 |
+
}
|
| 65 |
+
|
| 66 |
+
.input-focus:focus {
|
| 67 |
+
box-shadow: 0 0 0 3px rgba(139, 92, 246, 0.3);
|
| 68 |
+
}
|
| 69 |
+
</style>
|
| 70 |
+
</head>
|
| 71 |
+
<body class="bg-gray-100">
|
| 72 |
+
|
| 73 |
+
<div class="min-h-screen flex">
|
| 74 |
+
<!-- Left Section (Banner / Design / Info) -->
|
| 75 |
+
<div class="hidden lg:flex w-1/2 mystery-bg text-white flex-col justify-center items-center p-12 relative">
|
| 76 |
+
<div class="relative z-10 text-center">
|
| 77 |
+
<div class="absolute -top-16 left-1/2 transform -translate-x-1/2">
|
| 78 |
+
<div class="w-32 h-32 bg-white bg-opacity-20 rounded-full flex items-center justify-center">
|
| 79 |
+
<i class="fas fa-gift text-6xl text-white animate-float"></i>
|
| 80 |
+
</div>
|
| 81 |
+
</div>
|
| 82 |
+
<h1 class="text-5xl font-bold mb-6 mt-8">Welcome Back <span class="text-yellow-300">🎁</span></h1>
|
| 83 |
+
<p class="text-xl mb-8 max-w-md mx-auto leading-relaxed">Log in and unlock your MysteryBox surprises! Exclusive deals and rewards await.</p>
|
| 84 |
+
<div class="bg-white bg-opacity-10 p-6 rounded-2xl backdrop-blur-sm border border-white border-opacity-20">
|
| 85 |
+
<h3 class="text-xl font-semibold mb-3">Why join us?</h3>
|
| 86 |
+
<ul class="space-y-2 text-left">
|
| 87 |
+
<li class="flex items-center"><i class="fas fa-check-circle text-emerald-300 mr-2"></i> Exclusive mystery deals</li>
|
| 88 |
+
<li class="flex items-center"><i class="fas fa-check-circle text-emerald-300 mr-2"></i> Personalized recommendations</li>
|
| 89 |
+
<li class="flex items-center"><i class="fas fa-check-circle text-emerald-300 mr-2"></i> Early access to new boxes</li>
|
| 90 |
+
</ul>
|
| 91 |
+
</div>
|
| 92 |
+
</div>
|
| 93 |
+
|
| 94 |
+
<!-- Animated confetti -->
|
| 95 |
+
<div class="confetti" style="top: 20%; left: 30%; animation: fall 8s linear infinite 1s;"></div>
|
| 96 |
+
<div class="confetti" style="top: 10%; left: 60%; animation: fall 10s linear infinite 2s;"></div>
|
| 97 |
+
<div class="confetti" style="top: 15%; left: 80%; animation: fall 9s linear infinite 0.5s;"></div>
|
| 98 |
+
</div>
|
| 99 |
+
|
| 100 |
+
<!-- Right Section (Login Form) -->
|
| 101 |
+
<div class="w-full lg:w-1/2 flex flex-col justify-center items-center bg-white">
|
| 102 |
+
<div class="max-w-md w-full p-8 space-y-6">
|
| 103 |
+
<div class="text-center">
|
| 104 |
+
<h2 class="text-4xl font-bold text-gray-900 bg-clip-text text-transparent bg-gradient-to-r from-purple-600 to-purple-400">Login</h2>
|
| 105 |
+
<p class="text-gray-600 mt-2">Enter your credentials to continue your mystery journey</p>
|
| 106 |
+
</div>
|
| 107 |
+
|
| 108 |
+
<!-- Form -->
|
| 109 |
+
<form method="POST" class="mt-8 space-y-6">
|
| 110 |
+
{% csrf_token %}
|
| 111 |
+
<div class="relative">
|
| 112 |
+
<label class="block text-gray-700 font-medium mb-2">Email</label>
|
| 113 |
+
<div class="relative">
|
| 114 |
+
<i class="fas fa-envelope absolute left-3 top-3 text-gray-400"></i>
|
| 115 |
+
<input type="email" name="email" required class="w-full pl-10 pr-3 py-3 border border-gray-300 rounded-xl focus:outline-none input-focus focus:border-purple-500 transition duration-300" placeholder="Enter your email">
|
| 116 |
+
</div>
|
| 117 |
+
</div>
|
| 118 |
+
<div class="relative">
|
| 119 |
+
<label class="block text-gray-700 font-medium mb-2">Password</label>
|
| 120 |
+
<div class="relative">
|
| 121 |
+
<i class="fas fa-lock absolute left-3 top-3 text-gray-400"></i>
|
| 122 |
+
<input type="password" name="password" required class="w-full pl-10 pr-3 py-3 border border-gray-300 rounded-xl focus:outline-none input-focus focus:border-purple-500 transition duration-300" placeholder="Enter your password">
|
| 123 |
+
</div>
|
| 124 |
+
</div>
|
| 125 |
+
<div class="flex justify-between items-center text-sm">
|
| 126 |
+
<label class="flex items-center">
|
| 127 |
+
<input type="checkbox" class="form-checkbox h-4 w-4 text-purple-600 rounded focus:ring-purple-500">
|
| 128 |
+
<span class="ml-2 text-gray-700">Remember me</span>
|
| 129 |
+
</label>
|
| 130 |
+
<a href="/accounts/reset-password" class="text-purple-600 hover:text-purple-800 transition duration-300 font-medium">Forgot Password?</a>
|
| 131 |
+
</div>
|
| 132 |
+
<button type="submit" class="w-full py-3 px-4 bg-gradient-to-r from-purple-700 to-purple-500 hover:from-purple-600 hover:to-purple-400 text-white font-semibold rounded-xl shadow-md transition duration-300 btn-glow flex items-center justify-center">
|
| 133 |
+
<span>Login</span>
|
| 134 |
+
<i class="fas fa-arrow-right ml-2"></i>
|
| 135 |
+
</button>
|
| 136 |
+
</form>
|
| 137 |
+
|
| 138 |
+
<!-- Divider -->
|
| 139 |
+
<div class="flex items-center my-6">
|
| 140 |
+
<div class="flex-grow border-t border-gray-300"></div>
|
| 141 |
+
<span class="px-3 text-gray-500 text-sm">OR</span>
|
| 142 |
+
<div class="flex-grow border-t border-gray-300"></div>
|
| 143 |
+
</div>
|
| 144 |
+
|
| 145 |
+
<!-- Social Login -->
|
| 146 |
+
<div class="flex justify-center space-x-4">
|
| 147 |
+
<a href="#" class="px-4 py-2.5 bg-blue-600 text-white rounded-xl shadow hover:bg-blue-700 transition duration-300 flex items-center space-x-2">
|
| 148 |
+
<i class="fab fa-facebook-f"></i>
|
| 149 |
+
<span>Facebook</span>
|
| 150 |
+
</a>
|
| 151 |
+
<a href="#" class="px-4 py-2.5 bg-red-500 text-white rounded-xl shadow hover:bg-red-600 transition duration-300 flex items-center space-x-2">
|
| 152 |
+
<i class="fab fa-google"></i>
|
| 153 |
+
<span>Google</span>
|
| 154 |
+
</a>
|
| 155 |
+
</div>
|
| 156 |
+
|
| 157 |
+
<!-- Signup Redirect -->
|
| 158 |
+
<p class="text-center text-gray-600 pt-4">
|
| 159 |
+
Don't have an account?
|
| 160 |
+
<a href="/Accounts/signup" class="text-purple-600 font-medium hover:text-purple-800 transition duration-300">Sign Up</a>
|
| 161 |
+
</p>
|
| 162 |
+
</div>
|
| 163 |
+
</div>
|
| 164 |
+
</div>
|
| 165 |
+
|
| 166 |
+
<style>
|
| 167 |
+
.confetti {
|
| 168 |
+
position: absolute;
|
| 169 |
+
width: 10px;
|
| 170 |
+
height: 10px;
|
| 171 |
+
background-color: rgba(255, 255, 255, 0.7);
|
| 172 |
+
opacity: 0;
|
| 173 |
+
}
|
| 174 |
+
|
| 175 |
+
@keyframes fall {
|
| 176 |
+
0% {
|
| 177 |
+
opacity: 1;
|
| 178 |
+
transform: translateY(0) rotate(0deg);
|
| 179 |
+
}
|
| 180 |
+
100% {
|
| 181 |
+
opacity: 0;
|
| 182 |
+
transform: translateY(100vh) rotate(360deg);
|
| 183 |
+
}
|
| 184 |
+
}
|
| 185 |
+
</style>
|
| 186 |
+
|
| 187 |
+
</body>
|
| 188 |
+
</html>
|
MistryMart/Accounts/templates/signup.html
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>MysteryBox - Sign Up</title>
|
| 7 |
+
<script src="https://cdn.tailwindcss.com"></script>
|
| 8 |
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
| 9 |
+
<script>
|
| 10 |
+
tailwind.config = {
|
| 11 |
+
theme: {
|
| 12 |
+
extend: {
|
| 13 |
+
animation: {
|
| 14 |
+
'float': 'float 6s ease-in-out infinite',
|
| 15 |
+
'pulse-slow': 'pulse 4s cubic-bezier(0.4, 0, 0.6, 1) infinite',
|
| 16 |
+
},
|
| 17 |
+
keyframes: {
|
| 18 |
+
float: {
|
| 19 |
+
'0%, 100%': { transform: 'translateY(0)' },
|
| 20 |
+
'50%': { transform: 'translateY(-10px)' },
|
| 21 |
+
}
|
| 22 |
+
}
|
| 23 |
+
}
|
| 24 |
+
}
|
| 25 |
+
}
|
| 26 |
+
</script>
|
| 27 |
+
<style>
|
| 28 |
+
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap');
|
| 29 |
+
|
| 30 |
+
body {
|
| 31 |
+
font-family: 'Poppins', sans-serif;
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
.signup-bg {
|
| 35 |
+
background: linear-gradient(135deg, #F59E0B 0%, #F97316 100%);
|
| 36 |
+
position: relative;
|
| 37 |
+
overflow: hidden;
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
.signup-bg::before {
|
| 41 |
+
content: "";
|
| 42 |
+
position: absolute;
|
| 43 |
+
width: 200%;
|
| 44 |
+
height: 200%;
|
| 45 |
+
top: -50%;
|
| 46 |
+
left: -50%;
|
| 47 |
+
z-index: 0;
|
| 48 |
+
background: radial-gradient(circle, rgba(255,255,255,0.15) 10%, transparent 10.5%);
|
| 49 |
+
background-size: 25px 25px;
|
| 50 |
+
transform: rotate(30deg);
|
| 51 |
+
animation: pulse-slow 8s infinite;
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
.confetti {
|
| 55 |
+
position: absolute;
|
| 56 |
+
width: 10px;
|
| 57 |
+
height: 10px;
|
| 58 |
+
background-color: rgba(255, 255, 255, 0.5);
|
| 59 |
+
opacity: 0;
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
.btn-glow:hover {
|
| 63 |
+
box-shadow: 0 0 15px rgba(245, 158, 11, 0.6);
|
| 64 |
+
}
|
| 65 |
+
|
| 66 |
+
.input-focus:focus {
|
| 67 |
+
box-shadow: 0 0 0 3px rgba(245, 158, 11, 0.3);
|
| 68 |
+
}
|
| 69 |
+
</style>
|
| 70 |
+
</head>
|
| 71 |
+
<body class="bg-gray-100">
|
| 72 |
+
|
| 73 |
+
<div class="min-h-screen flex">
|
| 74 |
+
<!-- Left Section (Banner / Fun / Marketing) -->
|
| 75 |
+
<div class="hidden lg:flex w-1/2 signup-bg text-black flex-col justify-center items-center p-12 relative">
|
| 76 |
+
<div class="relative z-10 text-center">
|
| 77 |
+
<div class="absolute -top-16 left-1/2 transform -translate-x-1/2">
|
| 78 |
+
<div class="w-32 h-32 bg-white bg-opacity-30 rounded-full flex items-center justify-center">
|
| 79 |
+
<i class="fas fa-box-open text-6xl text-white animate-float"></i>
|
| 80 |
+
</div>
|
| 81 |
+
</div>
|
| 82 |
+
<h1 class="text-5xl font-bold mb-6 mt-8">Join the Mystery! <span class="text-purple-600">🎉</span></h1>
|
| 83 |
+
<p class="text-xl mb-8 max-w-md mx-auto leading-relaxed">Create your account and start unboxing happiness. Deals, rewards, and surprises await every member.</p>
|
| 84 |
+
<div class="bg-white bg-opacity-20 p-6 rounded-2xl backdrop-blur-sm border border-white border-opacity-30">
|
| 85 |
+
<h3 class="text-xl font-semibold mb-3">Member Benefits</h3>
|
| 86 |
+
<ul class="space-y-2 text-left">
|
| 87 |
+
<li class="flex items-center"><i class="fas fa-star text-yellow-700 mr-2"></i> Curated mystery boxes</li>
|
| 88 |
+
<li class="flex items-center"><i class="fas fa-star text-yellow-700 mr-2"></i> Special birthday surprises</li>
|
| 89 |
+
<li class="flex items-center"><i class="fas fa-star text-yellow-700 mr-2"></i> Member-only discounts</li>
|
| 90 |
+
<li class="flex items-center"><i class="fas fa-star text-yellow-700 mr-2"></i> Early access to sales</li>
|
| 91 |
+
</ul>
|
| 92 |
+
</div>
|
| 93 |
+
</div>
|
| 94 |
+
|
| 95 |
+
<!-- Animated confetti -->
|
| 96 |
+
<div class="confetti" style="top: 20%; left: 30%; animation: fall 8s linear infinite 1s;"></div>
|
| 97 |
+
<div class="confetti" style="top: 10%; left: 60%; animation: fall 10s linear infinite 2s;"></div>
|
| 98 |
+
<div class="confetti" style="top: 15%; left: 80%; animation: fall 9s linear infinite 0.5s;"></div>
|
| 99 |
+
</div>
|
| 100 |
+
|
| 101 |
+
<!-- Right Section (Signup Form) -->
|
| 102 |
+
<div class="w-full lg:w-1/2 flex flex-col justify-center items-center bg-white">
|
| 103 |
+
<div class="max-w-md w-full p-8 space-y-6">
|
| 104 |
+
<div class="text-center">
|
| 105 |
+
<h2 class="text-4xl font-bold text-gray-900 bg-clip-text text-transparent bg-gradient-to-r from-yellow-600 to-orange-500">Sign Up</h2>
|
| 106 |
+
<p class="text-gray-600 mt-2">Fill in your details to start your mystery adventure</p>
|
| 107 |
+
</div>
|
| 108 |
+
|
| 109 |
+
<!-- Form -->
|
| 110 |
+
<form method="POST" class="mt-8 space-y-4">
|
| 111 |
+
{% csrf_token %}
|
| 112 |
+
<div class="grid grid-cols-2 gap-4">
|
| 113 |
+
<div>
|
| 114 |
+
<label class="block text-gray-700 font-medium mb-2">First Name</label>
|
| 115 |
+
<div class="relative">
|
| 116 |
+
<i class="fas fa-user absolute left-3 top-3 text-gray-400"></i>
|
| 117 |
+
<input type="text" name="first_name" required class="w-full pl-10 pr-3 py-3 border border-gray-300 rounded-xl focus:outline-none input-focus focus:border-yellow-500 transition duration-300" placeholder="First name">
|
| 118 |
+
</div>
|
| 119 |
+
</div>
|
| 120 |
+
<div>
|
| 121 |
+
<label class="block text-gray-700 font-medium mb-2">Last Name</label>
|
| 122 |
+
<div class="relative">
|
| 123 |
+
<i class="fas fa-user absolute left-3 top-3 text-gray-400"></i>
|
| 124 |
+
<input type="text" name="last_name" required class="w-full pl-10 pr-3 py-3 border border-gray-300 rounded-xl focus:outline-none input-focus focus:border-yellow-500 transition duration-300" placeholder="Last name">
|
| 125 |
+
</div>
|
| 126 |
+
</div>
|
| 127 |
+
</div>
|
| 128 |
+
<div>
|
| 129 |
+
<label class="block text-gray-700 font-medium mb-2">Email</label>
|
| 130 |
+
<div class="relative">
|
| 131 |
+
<i class="fas fa-envelope absolute left-3 top-3 text-gray-400"></i>
|
| 132 |
+
<input type="email" name="email" required class="w-full pl-10 pr-3 py-3 border border-gray-300 rounded-xl focus:outline-none input-focus focus:border-yellow-500 transition duration-300" placeholder="Enter your email">
|
| 133 |
+
</div>
|
| 134 |
+
</div>
|
| 135 |
+
<div>
|
| 136 |
+
<label class="block text-gray-700 font-medium mb-2">Password</label>
|
| 137 |
+
<div class="relative">
|
| 138 |
+
<i class="fas fa-lock absolute left-3 top-3 text-gray-400"></i>
|
| 139 |
+
<input type="password" name="password1" required class="w-full pl-10 pr-3 py-3 border border-gray-300 rounded-xl focus:outline-none input-focus focus:border-yellow-500 transition duration-300" placeholder="Create a password">
|
| 140 |
+
</div>
|
| 141 |
+
</div>
|
| 142 |
+
<div>
|
| 143 |
+
<label class="block text-gray-700 font-medium mb-2">Confirm Password</label>
|
| 144 |
+
<div class="relative">
|
| 145 |
+
<i class="fas fa-lock absolute left-3 top-3 text-gray-400"></i>
|
| 146 |
+
<input type="password" name="password2" required class="w-full pl-10 pr-3 py-3 border border-gray-300 rounded-xl focus:outline-none input-focus focus:border-yellow-500 transition duration-300" placeholder="Confirm your password">
|
| 147 |
+
</div>
|
| 148 |
+
</div>
|
| 149 |
+
<div class="flex items-center text-sm pt-2">
|
| 150 |
+
<label class="flex items-center">
|
| 151 |
+
<input type="checkbox" class="form-checkbox h-4 w-4 text-yellow-600 rounded focus:ring-yellow-500">
|
| 152 |
+
<span class="ml-2 text-gray-700">I agree to the <a href="#" class="text-yellow-600 hover:underline">Terms & Conditions</a></span>
|
| 153 |
+
</label>
|
| 154 |
+
</div>
|
| 155 |
+
<button type="submit" class="w-full py-3 px-4 bg-gradient-to-r from-yellow-500 to-orange-500 hover:from-yellow-400 hover:to-orange-400 text-black font-semibold rounded-xl shadow-md transition duration-300 btn-glow flex items-center justify-center">
|
| 156 |
+
<span>Create Account</span>
|
| 157 |
+
<i class="fas fa-gift ml-2"></i>
|
| 158 |
+
</button>
|
| 159 |
+
</form>
|
| 160 |
+
|
| 161 |
+
<!-- Divider -->
|
| 162 |
+
<div class="flex items-center my-6">
|
| 163 |
+
<div class="flex-grow border-t border-gray-300"></div>
|
| 164 |
+
<span class="px-3 text-gray-500 text-sm">OR</span>
|
| 165 |
+
<div class="flex-grow border-t border-gray-300"></div>
|
| 166 |
+
</div>
|
| 167 |
+
|
| 168 |
+
<!-- Social Signup -->
|
| 169 |
+
<div class="flex justify-center space-x-4">
|
| 170 |
+
<a href="#" class="px-4 py-2.5 bg-blue-600 text-white rounded-xl shadow hover:bg-blue-700 transition duration-300 flex items-center space-x-2">
|
| 171 |
+
<i class="fab fa-facebook-f"></i>
|
| 172 |
+
<span>Facebook</span>
|
| 173 |
+
</a>
|
| 174 |
+
<a href="#" class="px-4 py-2.5 bg-red-500 text-white rounded-xl shadow hover:bg-red-600 transition duration-300 flex items-center space-x-2">
|
| 175 |
+
<i class="fab fa-google"></i>
|
| 176 |
+
<span>Google</span>
|
| 177 |
+
</a>
|
| 178 |
+
</div>
|
| 179 |
+
|
| 180 |
+
<!-- Login Redirect -->
|
| 181 |
+
<p class="text-center text-gray-600 pt-4">
|
| 182 |
+
Already have an account?
|
| 183 |
+
<a href="/Accounts/login" class="text-yellow-600 font-medium hover:text-yellow-800 transition duration-300">Login</a>
|
| 184 |
+
</p>
|
| 185 |
+
</div>
|
| 186 |
+
</div>
|
| 187 |
+
</div>
|
| 188 |
+
|
| 189 |
+
<style>
|
| 190 |
+
.confetti {
|
| 191 |
+
position: absolute;
|
| 192 |
+
width: 10px;
|
| 193 |
+
height: 10px;
|
| 194 |
+
background-color: rgba(255, 255, 255, 0.7);
|
| 195 |
+
opacity: 0;
|
| 196 |
+
}
|
| 197 |
+
|
| 198 |
+
@keyframes fall {
|
| 199 |
+
0% {
|
| 200 |
+
opacity: 1;
|
| 201 |
+
transform: translateY(0) rotate(0deg);
|
| 202 |
+
}
|
| 203 |
+
100% {
|
| 204 |
+
opacity: 0;
|
| 205 |
+
transform: translateY(100vh) rotate(360deg);
|
| 206 |
+
}
|
| 207 |
+
}
|
| 208 |
+
</style>
|
| 209 |
+
|
| 210 |
+
</body>
|
| 211 |
+
</html>
|
MistryMart/Accounts/tests.py
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from django.test import TestCase
|
| 2 |
+
|
| 3 |
+
# Create your tests here.
|
MistryMart/Accounts/urls.py
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from django.contrib import admin
|
| 2 |
+
from django.urls import path
|
| 3 |
+
from Accounts import views
|
| 4 |
+
from django.contrib.auth import views as auth_views
|
| 5 |
+
from . import *
|
| 6 |
+
|
| 7 |
+
urlpatterns = [
|
| 8 |
+
path("login", views.login , name="login"),
|
| 9 |
+
path("signup", views.signup , name="signup"),
|
| 10 |
+
path("logout/", views.logout_view , name="logout"),
|
| 11 |
+
|
| 12 |
+
]
|
MistryMart/Accounts/views.py
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from django.shortcuts import render , HttpResponse , redirect
|
| 2 |
+
from django.contrib.auth import login as log , authenticate , logout
|
| 3 |
+
from Accounts.models import User
|
| 4 |
+
from django.contrib import messages
|
| 5 |
+
|
| 6 |
+
# Create your views here.
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
def login(request):
|
| 11 |
+
if request.method == 'POST':
|
| 12 |
+
email = request.POST.get('email')
|
| 13 |
+
password = request.POST.get('password')
|
| 14 |
+
user = authenticate(request, email=email, password=password)
|
| 15 |
+
if user is not None:
|
| 16 |
+
log(request, user)
|
| 17 |
+
|
| 18 |
+
return redirect('/')
|
| 19 |
+
else:
|
| 20 |
+
|
| 21 |
+
return render(request, 'login.html', {'error_message': 'Invalid email or password'})
|
| 22 |
+
else:
|
| 23 |
+
return render(request, 'Accounts/templates/login.html' )
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
def signup(request):
|
| 28 |
+
if request.method == "POST":
|
| 29 |
+
first_name = request.POST.get("first_name")
|
| 30 |
+
last_name = request.POST.get("last_name")
|
| 31 |
+
email = request.POST.get("email")
|
| 32 |
+
password1 = request.POST.get("password1")
|
| 33 |
+
password2 = request.POST.get("password2")
|
| 34 |
+
|
| 35 |
+
# Validation
|
| 36 |
+
if password1 != password2:
|
| 37 |
+
messages.error(request, "Passwords do not match.")
|
| 38 |
+
return redirect("/Accounts/signup")
|
| 39 |
+
|
| 40 |
+
if User.objects.filter(email=email).exists():
|
| 41 |
+
messages.error(request, "Email already registered.")
|
| 42 |
+
return redirect("/Accounts/signup")
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
user = User.objects.create_user(
|
| 46 |
+
email=email,
|
| 47 |
+
first_name=first_name,
|
| 48 |
+
last_name=last_name,
|
| 49 |
+
password=password1,
|
| 50 |
+
)
|
| 51 |
+
return redirect('/')
|
| 52 |
+
else:
|
| 53 |
+
return render(request, 'Accounts/templates/signup.html' )
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
def logout_view(request):
|
| 57 |
+
logout(request)
|
| 58 |
+
return redirect('/')
|
MistryMart/Analytics/__init__.py
ADDED
|
File without changes
|
MistryMart/Analytics/__pycache__/__init__.cpython-313.pyc
ADDED
|
Binary file (143 Bytes). View file
|
|
|
MistryMart/Analytics/__pycache__/admin.cpython-313.pyc
ADDED
|
Binary file (1.15 kB). View file
|
|
|
MistryMart/Analytics/__pycache__/apps.cpython-313.pyc
ADDED
|
Binary file (513 Bytes). View file
|
|
|
MistryMart/Analytics/__pycache__/models.cpython-313.pyc
ADDED
|
Binary file (1.99 kB). View file
|
|
|
MistryMart/Analytics/admin.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from django.contrib import admin
|
| 2 |
+
from .models import SalesReport, UserStats
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
class SalesReportAdmin(admin.ModelAdmin):
|
| 6 |
+
list_display = ('date', 'total_orders', 'total_revenue', 'top_box')
|
| 7 |
+
list_filter = ('date',)
|
| 8 |
+
search_fields = ('top_box__title',)
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
class UserStatsAdmin(admin.ModelAdmin):
|
| 12 |
+
list_display = ('user', 'total_spent', 'boxes_purchased', 'last_active')
|
| 13 |
+
search_fields = ('user__email',)
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
admin.site.register(SalesReport, SalesReportAdmin)
|
| 17 |
+
admin.site.register(UserStats, UserStatsAdmin)
|
MistryMart/Analytics/apps.py
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from django.apps import AppConfig
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
class AnalyticsConfig(AppConfig):
|
| 5 |
+
default_auto_field = 'django.db.models.BigAutoField'
|
| 6 |
+
name = 'Analytics'
|
MistryMart/Analytics/migrations/0001_initial.py
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Generated by Django 5.2.4 on 2025-08-18 10:42
|
| 2 |
+
|
| 3 |
+
import django.db.models.deletion
|
| 4 |
+
from django.db import migrations, models
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
class Migration(migrations.Migration):
|
| 8 |
+
|
| 9 |
+
initial = True
|
| 10 |
+
|
| 11 |
+
dependencies = [
|
| 12 |
+
('Accounts', '0001_initial'),
|
| 13 |
+
('Boxes', '0001_initial'),
|
| 14 |
+
]
|
| 15 |
+
|
| 16 |
+
operations = [
|
| 17 |
+
migrations.CreateModel(
|
| 18 |
+
name='SalesReport',
|
| 19 |
+
fields=[
|
| 20 |
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
| 21 |
+
('date', models.DateField()),
|
| 22 |
+
('total_orders', models.IntegerField()),
|
| 23 |
+
('total_revenue', models.DecimalField(decimal_places=2, max_digits=12)),
|
| 24 |
+
('top_box', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='Boxes.mysterybox')),
|
| 25 |
+
],
|
| 26 |
+
),
|
| 27 |
+
migrations.CreateModel(
|
| 28 |
+
name='UserStats',
|
| 29 |
+
fields=[
|
| 30 |
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
| 31 |
+
('total_spent', models.DecimalField(decimal_places=2, default=0.0, max_digits=12)),
|
| 32 |
+
('boxes_purchased', models.IntegerField(default=0)),
|
| 33 |
+
('last_active', models.DateTimeField(auto_now=True)),
|
| 34 |
+
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='Accounts.profile')),
|
| 35 |
+
],
|
| 36 |
+
),
|
| 37 |
+
]
|
MistryMart/Analytics/migrations/__init__.py
ADDED
|
File without changes
|
MistryMart/Analytics/migrations/__pycache__/0001_initial.cpython-313.pyc
ADDED
|
Binary file (2.09 kB). View file
|
|
|
MistryMart/Analytics/migrations/__pycache__/__init__.cpython-313.pyc
ADDED
|
Binary file (154 Bytes). View file
|
|
|
MistryMart/Analytics/models.py
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from django.db import models
|
| 2 |
+
from Boxes.models import MysteryBox
|
| 3 |
+
from Accounts.models import Profile
|
| 4 |
+
|
| 5 |
+
class SalesReport(models.Model):
|
| 6 |
+
date = models.DateField()
|
| 7 |
+
total_orders = models.IntegerField()
|
| 8 |
+
total_revenue = models.DecimalField(max_digits=12, decimal_places=2)
|
| 9 |
+
top_box = models.ForeignKey(MysteryBox, on_delete=models.SET_NULL, null=True, blank=True)
|
| 10 |
+
|
| 11 |
+
def __str__(self):
|
| 12 |
+
return f"Sales Report - {self.date}"
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
class UserStats(models.Model):
|
| 16 |
+
user = models.OneToOneField(Profile, on_delete=models.CASCADE)
|
| 17 |
+
total_spent = models.DecimalField(max_digits=12, decimal_places=2, default=0.00)
|
| 18 |
+
boxes_purchased = models.IntegerField(default=0)
|
| 19 |
+
last_active = models.DateTimeField(auto_now=True)
|
| 20 |
+
|
| 21 |
+
def __str__(self):
|
| 22 |
+
return f"Stats for {self.user.user.username}"
|