sma / index.html
Marv12's picture
Add 3 files
551e537 verified
<!DOCTYPE html>
<html>
<head>
<title>Temu Clone - Backend Setup</title>
<style>
body {
font-family: Arial, sans-serif;
line-height: 1.6;
margin: 0;
padding: 20px;
background-color: #f5f5f5;
}
.container {
max-width: 1200px;
margin: 0 auto;
background: white;
padding: 20px;
border-radius: 5px;
box-shadow: 0 0 10px rgba(0,0,0,0.1);
}
h1, h2, h3 {
color: #333;
}
code {
background: #f4f4f4;
padding: 2px 5px;
border-radius: 3px;
font-family: monospace;
}
pre {
background: #333;
color: #fff;
padding: 10px;
border-radius: 5px;
overflow-x: auto;
}
.section {
margin-bottom: 30px;
padding-bottom: 20px;
border-bottom: 1px solid #eee;
}
.note {
background: #fffde7;
padding: 10px;
border-left: 4px solid #ffd600;
margin: 10px 0;
}
</style>
</head>
<body>
<div class="container">
<h1>Temu Clone - Backend Setup</h1>
<div class="section">
<h2>1. Backend Setup</h2>
<h3>Python Requirements</h3>
<p>Create a <code>requirements.txt</code> file:</p>
<pre>
Flask==2.3.2
Flask-SQLAlchemy==3.0.3
Flask-Login==0.6.2
Flask-Admin==1.6.1
Flask-WTF==1.0.1
python-dotenv==1.0.0
Pillow==9.5.0
</pre>
<h3>Configuration</h3>
<p>Create <code>config.py</code>:</p>
<pre>
import os
from dotenv import load_dotenv
load_dotenv()
class Config:
SECRET_KEY = os.getenv('SECRET_KEY') or 'your-secret-key-here'
SQLALCHEMY_DATABASE_URI = os.getenv('DATABASE_URL') or 'sqlite:///site.db'
SQLALCHEMY_TRACK_MODIFICATIONS = False
UPLOAD_FOLDER = 'uploads'
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}
# Admin credentials
ADMIN_EMAIL = os.getenv('ADMIN_EMAIL') or 'admin@example.com'
ADMIN_PASSWORD = os.getenv('ADMIN_PASSWORD') or 'admin123'
</pre>
<h3>Database Models</h3>
<p>Create <code>models.py</code>:</p>
<pre>
from datetime import datetime
from flask_sqlalchemy import SQLAlchemy
from flask_login import UserMixin
from werkzeug.security import generate_password_hash, check_password_hash
db = SQLAlchemy()
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(50), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
password_hash = db.Column(db.String(128))
is_admin = db.Column(db.Boolean, default=False)
date_created = db.Column(db.DateTime, default=datetime.utcnow)
orders = db.relationship('Order', backref='customer', lazy=True)
def set_password(self, password):
self.password_hash = generate_password_hash(password)
def check_password(self, password):
return check_password_hash(self.password_hash, password)
class Product(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), nullable=False)
description = db.Column(db.Text)
price = db.Column(db.Float, nullable=False)
original_price = db.Column(db.Float)
image = db.Column(db.String(100))
category = db.Column(db.String(50))
flash_sale = db.Column(db.Boolean, default=False)
rating = db.Column(db.Float, default=0)
reviews = db.Column(db.Integer, default=0)
date_added = db.Column(db.DateTime, default=datetime.utcnow)
order_items = db.relationship('OrderItem', backref='product', lazy=True)
class Order(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
total = db.Column(db.Float, nullable=False)
status = db.Column(db.String(20), default='Pending')
payment_method = db.Column(db.String(50))
shipping_address = db.Column(db.Text)
billing_address = db.Column(db.Text)
date_ordered = db.Column(db.DateTime, default=datetime.utcnow)
items = db.relationship('OrderItem', backref='order', lazy=True)
class OrderItem(db.Model):
id = db.Column(db.Integer, primary_key=True)
order_id = db.Column(db.Integer, db.ForeignKey('order.id'), nullable=False)
product_id = db.Column(db.Integer, db.ForeignKey('product.id'), nullable=False)
quantity = db.Column(db.Integer, nullable=False)
price = db.Column(db.Float, nullable=False)
</pre>
</div>
<div class="section">
<h2>2. Flask Application</h2>
<p>Create <code>app.py</code>:</p>
<pre>
import os
from flask import Flask, render_template, request, redirect, url_for, flash, send_from_directory
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager, login_user, login_required, logout_user, current_user
from flask_admin import Admin
from flask_admin.contrib.sqla import ModelView
from werkzeug.utils import secure_filename
from models import db, User, Product, Order, OrderItem
from config import Config
app = Flask(__name__)
app.config.from_object(Config)
# Initialize extensions
db.init_app(app)
login_manager = LoginManager(app)
login_manager.login_view = 'login'
# Create upload folder if not exists
if not os.path.exists(app.config['UPLOAD_FOLDER']):
os.makedirs(app.config['UPLOAD_FOLDER'])
@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
# Admin setup
class AdminModelView(ModelView):
def is_accessible(self):
return current_user.is_authenticated and current_user.is_admin
def inaccessible_callback(self, name, **kwargs):
return redirect(url_for('login'))
admin = Admin(app, name='Admin Panel', template_mode='bootstrap3')
admin.add_view(AdminModelView(User, db.session))
admin.add_view(AdminModelView(Product, db.session))
admin.add_view(AdminModelView(Order, db.session))
admin.add_view(AdminModelView(OrderItem, db.session))
# Routes
@app.route('/')
def home():
return render_template('admin/index.html')
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
email = request.form.get('email')
password = request.form.get('password')
user = User.query.filter_by(email=email).first()
if user and user.check_password(password):
login_user(user)
next_page = request.args.get('next')
return redirect(next_page or url_for('admin.index'))
else:
flash('Invalid email or password', 'danger')
return render_template('auth/login.html')
@app.route('/logout')
@login_required
def logout():
logout_user()
return redirect(url_for('login'))
# API Endpoints
@app.route('/api/products', methods=['GET'])
def get_products():
products = Product.query.all()
return {'products': [{
'id': p.id,
'name': p.name,
'price': p.price,
'original_price': p.original_price,
'image': url_for('uploaded_file', filename=p.image) if p.image else None,
'category': p.category,
'flash_sale': ,
'rating': p.rating,
'reviews': p.reviews
} for p in products]}
@app.route('/api/orders', methods=['POST'])
def create_order():
data = request.get_json()
# In a real app, you would validate the data and process payment
order = Order(
user_id=data.get('user_id'),
total=data['total'],
payment_method=data.get('payment_method', 'Credit Card'),
shipping_address=data.get('shipping_address', ''),
billing_address=data.get('billing_address', '')
)
db.session.add(order)
for item in data['items']:
order_item = OrderItem(
order_id=order.id,
product_id=item['product_id'],
quantity=item['quantity'],
price=item['price']
)
db.session.add(order_item)
db.session.commit()
return {'success': True, 'order_id': order.id}
@app.route('/uploads/<filename>')
def uploaded_file(filename):
return send_from_directory(app.config['UPLOAD_FOLDER'], filename)
# Create admin user on first run
def create_admin_user():
admin_email = app.config['ADMIN_EMAIL']
admin_password = app.config['ADMIN_PASSWORD']
if not User.query.filter_by(email=admin_email).first():
admin_user = User(
username='admin',
email=admin_email,
is_admin=True
)
admin_user.set_password(admin_password)
db.session.add(admin_user)
db.session.commit()
print("Admin user created successfully!")
if __name__ == '__main__':
with app.app_context():
db.create_all()
create_admin_user()
app.run(debug=True)
</pre>
</div>
<div class="section">
<h2>3. Admin Panel Templates</h2>
<h3>Login Template (templates/auth/login.html)</h3>
<pre>
&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;title&gt;Admin Login&lt;/title&gt;
&lt;link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div class="container mt-5"&gt;
&lt;div class="row justify-content-center"&gt;
&lt;div class="col-md-6 col-lg-4"&gt;
&lt;div class="card shadow"&gt;
&lt;div class="card-body"&gt;
&lt;h3 class="card-title text-center mb-4"&gt;Admin Login&lt;/h3&gt;
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
&lt;div class="alert alert-{{ category }}"&gt;{{ message }}&lt;/div&gt;
{% endfor %}
{% endif %}
{% endwith %}
&lt;form method="POST" action="{{ url_for('login') }}"&gt;
&lt;div class="mb-3"&gt;
&lt;label for="email" class="form-label"&gt;Email&lt;/label&gt;
&lt;input type="email" class="form-control" id="email" name="email" required&gt;
&lt;/div&gt;
&lt;div class="mb-3"&gt;
&lt;label for="password" class="form-label"&gt;Password&lt;/label&gt;
&lt;input type="password" class="form-control" id="password" name="password" required&gt;
&lt;/div&gt;
&lt;button type="submit" class="btn btn-primary w-100"&gt;Login&lt;/button&gt;
&lt;/form&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<h3>Admin Dashboard (templates/admin/index.html)</h3>
<pre>
{% extends 'admin/master.html' %}
{% block body %}
&lt;div class="container"&gt;
&lt;h1&gt;Admin Dashboard&lt;/h1&gt;
&lt;div class="row mt-4"&gt;
&lt;div class="col-md-4"&gt;
&lt;div class="card text-white bg-primary mb-3"&gt;
&lt;div class="card-body"&gt;
&lt;h5 class="card-title"&gt;Total Products&lt;/h5&gt;
&lt;p class="card-text" style="font-size: 2rem;"&gt;{{ Product.query.count() }}&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="col-md-4"&gt;
&lt;div class="card text-white bg-success mb-3"&gt;
&lt;div class="card-body"&gt;
&lt;h5 class="card-title"&gt;Total Orders&lt;/h5&gt;
&lt;p class="card-text" style="font-size: 2rem;"&gt;{{ Order.query.count() }}&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="col-md-4"&gt;
&lt;div class="card text-white bg-info mb-3"&gt;
&lt;div class="card-body"&gt;
&lt;h5 class="card-title"&gt;Total Users&lt;/h5&gt;
&lt;p class="card-text" style="font-size: 2rem;"&gt;{{ User.query.count() }}&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="row mt-4"&gt;
&lt;div class="col-md-6"&gt;
&lt;div class="card"&gt;
&lt;div class="card-header"&gt;
Recent Orders
&lt;/div&gt;
&lt;div class="card-body"&gt;
&lt;table class="table"&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;ID&lt;/th&gt;
&lt;th&gt;Date&lt;/th&gt;
&lt;th&gt;Total&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
{% for order in Order.query.order_by(Order.date_ordered.desc()).limit(5).all() %}
&lt;tr&gt;
&lt;td&gt;&lt;a href="{{ url_for('order.edit_view', id=order.id) }}"&gt;{{ order.id }}&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;{{ order.date_ordered.strftime('%Y-%m-%d') }}&lt;/td&gt;
&lt;td&gt;${{ "%.2f"|format(order.total) }}&lt;/td&gt;
&lt;td&gt;{{ order.status }}&lt;/td&gt;
&lt;/tr&gt;
{% endfor %}
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="col-md-6"&gt;
&lt;div class="card"&gt;
&lt;div class="card-header"&gt;
Recent Products
&lt;/div&gt;
&lt;div class="card-body"&gt;
&lt;table class="table"&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
{% for product in Product.query.order_by(Product.date_added.desc()).limit(5).all() %}
&lt;tr&gt;
&lt;td&gt;&lt;a href="{{ url_for('product.edit_view', id=product.id) }}"&gt;{{ product.name }}&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;${{ "%.2f"|format(product.price) }}&lt;/td&gt;
&lt;td&gt;{{ product.category }}&lt;/td&gt;
&lt;/tr&gt;
{% endfor %}
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
{% endblock %}
</pre>
</div>
<div class="section">
<h2>4. Integration with Frontend</h2>
<h3>Update your frontend JavaScript to use the API</h3>
<p>Modify your existing JavaScript to fetch products from the backend:</p>
<pre>
// Fetch products from backend
async function fetchProducts() {
try {
const response = await fetch('/api/products');
const data = await response.json();
return data.products;
} catch (error) {
console.error('Error fetching products:', error);
return [];
}
}
// Example of creating an order
async function createOrder(orderData) {
try {
const response = await fetch('/api/orders', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(orderData)
});
return await response.json();
} catch (error) {
console.error('Error creating order:', error);
return { success: false, error: 'Failed to create order' };
}
}
// Update your existing code to use these functions
document.addEventListener('DOMContentLoaded', async function() {
const products = await fetchProducts();
// Render products to the page
renderProducts(products);
// When user checks out
checkoutButton.addEventListener('click', async function() {
const orderData = {
user_id: currentUser?.id || null,
total: calculateCartTotal(),
items: cart.map(item => ({
product_id: item.id,
quantity: item.quantity,
price: item.price
})),
payment_method: 'Credit Card',
shipping_address: '123 Main St, Anytown, USA'
};
const result = await createOrder(orderData);
if (result.success) {
alert(`Order #${result.order_id} created successfully!`);
// Clear cart
cart = [];
localStorage.setItem('cart', JSON.stringify(cart));
updateCartCount();
renderCartItems();
} else {
alert('Failed to create order: ' + (result.error || 'Unknown error'));
}
});
});
</pre>
</div>
<div class="section">
<h2>5. Deployment Instructions</h2>
<div class="note">
<p><strong>Note:</strong> For production, you should use a proper web server like Gunicorn with Nginx, and a production database like PostgreSQL.</p>
</div>
<h3>Local Development</h3>
<ol>
<li>Install Python 3.8+</li>
<li>Create and activate a virtual environment:
<pre>python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate</pre>
</li>
<li>Install dependencies:
<pre>pip install -r requirements.txt</pre>
</li>
<li>Run the application:
<pre>python app.py</pre>
</li>
<li>Access the admin panel at <code>http://localhost:5000/admin</code></li>
<li>Login with the admin credentials from <code>config.py</code></li>
</ol>
<h3>Production Deployment</h3>
<p>For production, you'll need to:</p>
<ol>
<li>Set proper environment variables (SECRET_KEY, DATABASE_URL, etc.)</li>
<li>Use a production WSGI server like Gunicorn:
<pre>gunicorn -w 4 -b 0.0.0.0:5000 app:app</pre>
</li>
<li>Configure a reverse proxy like Nginx</li>
<li>Set up a production database (PostgreSQL recommended)</li>
<li>Configure HTTPS with Let's Encrypt</li>
</ol>
</div>
</div>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=Marv12/sma" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>