init
This commit is contained in:
16
app/templates/admin/add_category.html
Normal file
16
app/templates/admin/add_category.html
Normal file
@@ -0,0 +1,16 @@
|
||||
{% extends "admin/base.html" %}
|
||||
|
||||
{% block title %}Add Category - Digital Garage Sale{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h2>Add New Category</h2>
|
||||
|
||||
<form method="post" action="{{ url_for('admin.add_category') }}">
|
||||
<div class="form-group">
|
||||
<label for="name">Category Name</label>
|
||||
<input type="text" id="name" name="name" class="form-control" required>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Add Category</button>
|
||||
<a href="{{ url_for('admin.categories') }}" class="btn" style="margin-left: 0.5rem;">Cancel</a>
|
||||
</form>
|
||||
{% endblock %}
|
||||
52
app/templates/admin/add_item.html
Normal file
52
app/templates/admin/add_item.html
Normal file
@@ -0,0 +1,52 @@
|
||||
{% extends "admin/base.html" %}
|
||||
|
||||
{% block title %}Add Item - Digital Garage Sale{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h2>Add New Item</h2>
|
||||
|
||||
<form method="post" action="{{ url_for('admin.add_item') }}" enctype="multipart/form-data">
|
||||
<div class="form-group">
|
||||
<label for="title">Item Title</label>
|
||||
<input type="text" id="title" name="title" class="form-control" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="description">Description</label>
|
||||
<textarea id="description" name="description" class="form-control" rows="4" required></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="price">Price ($)</label>
|
||||
<input type="number" id="price" name="price" class="form-control" step="0.01" min="0" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="category_id">Category</label>
|
||||
<select id="category_id" name="category_id" class="form-control" required>
|
||||
<option value="">Select a category</option>
|
||||
{% for category in categories %}
|
||||
<option value="{{ category.id }}">{{ category.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="status">Status</label>
|
||||
<select id="status" name="status" class="form-control" required>
|
||||
<option value="For Sale">For Sale</option>
|
||||
<option value="On Hold">On Hold</option>
|
||||
<option value="Sold">Sold</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="image">Item Image</label>
|
||||
<input type="file" id="image" name="image" class="form-control">
|
||||
<small>Optional. Accepted formats: JPG, PNG, GIF</small>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary">Add Item</button>
|
||||
<a href="{{ url_for('admin.items') }}" class="btn" style="margin-left: 0.5rem;">Cancel</a>
|
||||
</form>
|
||||
{% endblock %}
|
||||
47
app/templates/admin/base.html
Normal file
47
app/templates/admin/base.html
Normal file
@@ -0,0 +1,47 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% block title %}Admin - Digital Garage Sale{% endblock %}</title>
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
|
||||
</head>
|
||||
<body>
|
||||
<header class="admin-header">
|
||||
<div class="container">
|
||||
<h1 class="admin-title">Digital Garage Sale Admin</h1>
|
||||
{% if session.get('admin_authenticated') %}
|
||||
<nav class="nav">
|
||||
<ul class="nav-list">
|
||||
<li class="nav-item"><a href="{{ url_for('main.index') }}">View Site</a></li>
|
||||
<li class="nav-item"><a href="{{ url_for('admin.dashboard') }}">Dashboard</a></li>
|
||||
<li class="nav-item"><a href="{{ url_for('admin.categories') }}">Categories</a></li>
|
||||
<li class="nav-item"><a href="{{ url_for('admin.items') }}">Items</a></li>
|
||||
<li class="nav-item"><a href="{{ url_for('admin.edit_contact') }}">Contact Info</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
{% endif %}
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="container">
|
||||
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||
{% if messages %}
|
||||
{% for category, message in messages %}
|
||||
<div class="alert alert-{{ category }}">
|
||||
{{ message }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
|
||||
{% block content %}{% endblock %}
|
||||
</main>
|
||||
|
||||
<footer class="site-footer">
|
||||
<div class="container">
|
||||
<p>© 2025 Digital Garage Sale Admin</p>
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
118
app/templates/admin/catalog_pdf.html
Normal file
118
app/templates/admin/catalog_pdf.html
Normal file
@@ -0,0 +1,118 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Garage Sale Catalog</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Times New Roman', serif;
|
||||
line-height: 1.6;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: #000;
|
||||
}
|
||||
.container {
|
||||
width: 90%;
|
||||
margin: 0 auto;
|
||||
padding: 1rem;
|
||||
}
|
||||
h1, h2, h3 {
|
||||
margin-top: 0;
|
||||
}
|
||||
.header {
|
||||
text-align: center;
|
||||
margin-bottom: 2rem;
|
||||
border-bottom: 1px solid #000;
|
||||
padding-bottom: 1rem;
|
||||
}
|
||||
.category {
|
||||
margin-bottom: 2rem;
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
.category-title {
|
||||
border-bottom: 1px solid #000;
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
.items-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 1rem;
|
||||
}
|
||||
.item {
|
||||
border: 1px solid #000;
|
||||
padding: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
.item-title {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
.item-price {
|
||||
font-weight: bold;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
.item-status {
|
||||
font-style: italic;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
.footer {
|
||||
margin-top: 2rem;
|
||||
text-align: center;
|
||||
border-top: 1px solid #000;
|
||||
padding-top: 1rem;
|
||||
}
|
||||
.page-break {
|
||||
page-break-after: always;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<h1>Digital Garage Sale Catalog</h1>
|
||||
<p>Printed on {{ now.strftime('%B %d, %Y') }}</p>
|
||||
</div>
|
||||
|
||||
<div class="contact-info">
|
||||
<h2>Contact Information</h2>
|
||||
<p><strong>Email:</strong> {{ contact_info.email }}</p>
|
||||
{% if contact_info.signal %}
|
||||
<p><strong>Signal:</strong> {{ contact_info.signal }}</p>
|
||||
{% endif %}
|
||||
{% if contact_info.donation_link %}
|
||||
<p><strong>Donations:</strong> {{ contact_info.donation_link }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="page-break"></div>
|
||||
|
||||
<h2>Items For Sale</h2>
|
||||
|
||||
{% for category in categories %}
|
||||
<div class="category">
|
||||
<h3 class="category-title">{{ category.name }}</h3>
|
||||
<div class="items-grid">
|
||||
{% for item in items if item.category_id == category.id %}
|
||||
<div class="item">
|
||||
<h4 class="item-title">{{ item.title }}</h4>
|
||||
<p class="item-price">${{ "%.2f"|format(item.price) }}</p>
|
||||
<p class="item-status">Status: {{ item.status }}</p>
|
||||
<p>{{ item.description }}</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if not loop.last %}
|
||||
<div class="page-break"></div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
<div class="footer">
|
||||
<p>All items are sold as-is. Please contact for more information.</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
38
app/templates/admin/categories.html
Normal file
38
app/templates/admin/categories.html
Normal file
@@ -0,0 +1,38 @@
|
||||
{% extends "admin/base.html" %}
|
||||
|
||||
{% block title %}Manage Categories - Digital Garage Sale{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h2>Manage Categories</h2>
|
||||
|
||||
<a href="{{ url_for('admin.add_category') }}" class="btn btn-primary" style="margin-bottom: 1rem;">Add New Category</a>
|
||||
|
||||
<table style="width: 100%; border-collapse: collapse; margin-top: 1rem;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="border: 1px solid #ddd; padding: 0.5rem; text-align: left;">ID</th>
|
||||
<th style="border: 1px solid #ddd; padding: 0.5rem; text-align: left;">Name</th>
|
||||
<th style="border: 1px solid #ddd; padding: 0.5rem; text-align: left;">Items Count</th>
|
||||
<th style="border: 1px solid #ddd; padding: 0.5rem; text-align: left;">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for category in categories %}
|
||||
<tr>
|
||||
<td style="border: 1px solid #ddd; padding: 0.5rem;">{{ category.id }}</td>
|
||||
<td style="border: 1px solid #ddd; padding: 0.5rem;">{{ category.name }}</td>
|
||||
<td style="border: 1px solid #ddd; padding: 0.5rem;">{{ category.items.count() }}</td>
|
||||
<td style="border: 1px solid #ddd; padding: 0.5rem;">
|
||||
<form method="post" action="{{ url_for('admin.delete_category', id=category.id) }}" style="display: inline;" onsubmit="return confirm('Are you sure you want to delete this category? All items in this category will also be deleted.');">
|
||||
<button type="submit" class="btn btn-danger">Delete</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="4" style="border: 1px solid #ddd; padding: 0.5rem; text-align: center;">No categories found</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endblock %}
|
||||
33
app/templates/admin/dashboard.html
Normal file
33
app/templates/admin/dashboard.html
Normal file
@@ -0,0 +1,33 @@
|
||||
{% extends "admin/base.html" %}
|
||||
|
||||
{% block title %}Admin Dashboard - Digital Garage Sale{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h2>Admin Dashboard</h2>
|
||||
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 1rem; margin-top: 2rem;">
|
||||
<div style="border: 1px solid #ddd; padding: 1rem; text-align: center;">
|
||||
<h3>Manage Categories</h3>
|
||||
<p>Add, edit, or remove item categories</p>
|
||||
<a href="{{ url_for('admin.categories') }}" class="btn btn-primary">Categories</a>
|
||||
</div>
|
||||
|
||||
<div style="border: 1px solid #ddd; padding: 1rem; text-align: center;">
|
||||
<h3>Manage Items</h3>
|
||||
<p>Add, edit, or remove items for sale</p>
|
||||
<a href="{{ url_for('admin.items') }}" class="btn btn-primary">Items</a>
|
||||
</div>
|
||||
|
||||
<div style="border: 1px solid #ddd; padding: 1rem; text-align: center;">
|
||||
<h3>Information</h3>
|
||||
<p>Update information and contact details</p>
|
||||
<a href="{{ url_for('admin.edit_contact') }}" class="btn btn-primary">Edit Information</a>
|
||||
</div>
|
||||
|
||||
<div style="border: 1px solid #ddd; padding: 1rem; text-align: center;">
|
||||
<h3>Generate Catalog</h3>
|
||||
<p>Create a PDF catalog of all items</p>
|
||||
<a href="{{ url_for('admin.generate_catalog') }}" class="btn btn-primary">Generate PDF</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
35
app/templates/admin/edit_contact.html
Normal file
35
app/templates/admin/edit_contact.html
Normal file
@@ -0,0 +1,35 @@
|
||||
{% extends "admin/base.html" %}
|
||||
|
||||
{% block title %}Edit Information - Digital Garage Sale{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h2>Edit Information</h2>
|
||||
|
||||
<form method="post" action="{{ url_for('admin.edit_contact') }}">
|
||||
<div class="form-group">
|
||||
<label for="information">Information Text</label>
|
||||
<textarea id="information" name="information" class="form-control" rows="6">{{ contact_info.information }}</textarea>
|
||||
<small>Provide general information about your garage sale that will be displayed at the top of the page.</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="email">Email Address</label>
|
||||
<input type="email" id="email" name="email" class="form-control" value="{{ contact_info.email }}" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="signal">Signal (Username or Phone Number)</label>
|
||||
<input type="text" id="signal" name="signal" class="form-control" value="{{ contact_info.signal }}">
|
||||
<small>Optional. Leave blank if you don't want to display Signal contact info.</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="donation_link">Donation Link</label>
|
||||
<input type="url" id="donation_link" name="donation_link" class="form-control" value="{{ contact_info.donation_link }}">
|
||||
<small>Optional. Full URL to your donation page.</small>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary">Update Information</button>
|
||||
<a href="{{ url_for('admin.dashboard') }}" class="btn" style="margin-left: 0.5rem;">Cancel</a>
|
||||
</form>
|
||||
{% endblock %}
|
||||
56
app/templates/admin/edit_item.html
Normal file
56
app/templates/admin/edit_item.html
Normal file
@@ -0,0 +1,56 @@
|
||||
{% extends "admin/base.html" %}
|
||||
|
||||
{% block title %}Edit Item - Digital Garage Sale{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h2>Edit Item</h2>
|
||||
|
||||
<form method="post" action="{{ url_for('admin.edit_item', id=item.id) }}" enctype="multipart/form-data">
|
||||
<div class="form-group">
|
||||
<label for="title">Item Title</label>
|
||||
<input type="text" id="title" name="title" class="form-control" value="{{ item.title }}" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="description">Description</label>
|
||||
<textarea id="description" name="description" class="form-control" rows="4" required>{{ item.description }}</textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="price">Price ($)</label>
|
||||
<input type="number" id="price" name="price" class="form-control" step="0.01" min="0" value="{{ item.price }}" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="category_id">Category</label>
|
||||
<select id="category_id" name="category_id" class="form-control" required>
|
||||
{% for category in categories %}
|
||||
<option value="{{ category.id }}" {% if category.id == item.category_id %}selected{% endif %}>{{ category.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="status">Status</label>
|
||||
<select id="status" name="status" class="form-control" required>
|
||||
<option value="For Sale" {% if item.status == 'For Sale' %}selected{% endif %}>For Sale</option>
|
||||
<option value="On Hold" {% if item.status == 'On Hold' %}selected{% endif %}>On Hold</option>
|
||||
<option value="Sold" {% if item.status == 'Sold' %}selected{% endif %}>Sold</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
{% if item.image_filename %}
|
||||
<p>Current image:</p>
|
||||
<img src="{{ url_for('static', filename='uploads/' + item.image_filename) }}" alt="{{ item.title }}" style="max-width: 200px; max-height: 200px; margin-bottom: 1rem;">
|
||||
{% endif %}
|
||||
|
||||
<label for="image">Change Item Image</label>
|
||||
<input type="file" id="image" name="image" class="form-control">
|
||||
<small>Optional. Leave empty to keep current image. Accepted formats: JPG, PNG, GIF</small>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary">Update Item</button>
|
||||
<a href="{{ url_for('admin.items') }}" class="btn" style="margin-left: 0.5rem;">Cancel</a>
|
||||
</form>
|
||||
{% endblock %}
|
||||
53
app/templates/admin/items.html
Normal file
53
app/templates/admin/items.html
Normal file
@@ -0,0 +1,53 @@
|
||||
{% extends "admin/base.html" %}
|
||||
|
||||
{% block title %}Manage Items - Digital Garage Sale{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h2>Manage Items</h2>
|
||||
|
||||
<a href="{{ url_for('admin.add_item') }}" class="btn btn-primary" style="margin-bottom: 1rem;">Add New Item</a>
|
||||
|
||||
<table style="width: 100%; border-collapse: collapse; margin-top: 1rem;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="border: 1px solid #ddd; padding: 0.5rem; text-align: left;">ID</th>
|
||||
<th style="border: 1px solid #ddd; padding: 0.5rem; text-align: left;">Image</th>
|
||||
<th style="border: 1px solid #ddd; padding: 0.5rem; text-align: left;">Title</th>
|
||||
<th style="border: 1px solid #ddd; padding: 0.5rem; text-align: left;">Price</th>
|
||||
<th style="border: 1px solid #ddd; padding: 0.5rem; text-align: left;">Category</th>
|
||||
<th style="border: 1px solid #ddd; padding: 0.5rem; text-align: left;">Status</th>
|
||||
<th style="border: 1px solid #ddd; padding: 0.5rem; text-align: left;">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in items %}
|
||||
<tr>
|
||||
<td style="border: 1px solid #ddd; padding: 0.5rem;">{{ item.id }}</td>
|
||||
<td style="border: 1px solid #ddd; padding: 0.5rem;">
|
||||
{% if item.image_filename %}
|
||||
<img src="{{ url_for('static', filename='uploads/' + item.image_filename) }}" alt="{{ item.title }}" style="width: 50px; height: 50px; object-fit: cover;">
|
||||
{% else %}
|
||||
No Image
|
||||
{% endif %}
|
||||
</td>
|
||||
<td style="border: 1px solid #ddd; padding: 0.5rem;">{{ item.title }}</td>
|
||||
<td style="border: 1px solid #ddd; padding: 0.5rem;">${{ "%.2f"|format(item.price) }}</td>
|
||||
<td style="border: 1px solid #ddd; padding: 0.5rem;">{{ item.category.name }}</td>
|
||||
<td style="border: 1px solid #ddd; padding: 0.5rem;">
|
||||
<span class="item-status status-{{ item.status|lower|replace(' ', '-') }}">{{ item.status }}</span>
|
||||
</td>
|
||||
<td style="border: 1px solid #ddd; padding: 0.5rem;">
|
||||
<a href="{{ url_for('admin.edit_item', id=item.id) }}" class="btn">Edit</a>
|
||||
<form method="post" action="{{ url_for('admin.delete_item', id=item.id) }}" style="display: inline;" onsubmit="return confirm('Are you sure you want to delete this item?');">
|
||||
<button type="submit" class="btn btn-danger">Delete</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="7" style="border: 1px solid #ddd; padding: 0.5rem; text-align: center;">No items found</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endblock %}
|
||||
21
app/templates/admin/login.html
Normal file
21
app/templates/admin/login.html
Normal file
@@ -0,0 +1,21 @@
|
||||
{% extends "admin/base.html" %}
|
||||
|
||||
{% block title %}Admin Login - Digital Garage Sale{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div style="max-width: 400px; margin: 0 auto;">
|
||||
<h2>Admin Login</h2>
|
||||
|
||||
<form method="post" action="{{ url_for('admin.login') }}">
|
||||
<div class="form-group">
|
||||
<label for="password">Password</label>
|
||||
<input type="password" id="password" name="password" class="form-control" required>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Login</button>
|
||||
</form>
|
||||
|
||||
<p style="margin-top: 20px;">
|
||||
<a href="{{ url_for('main.index') }}">← Back to site</a>
|
||||
</p>
|
||||
</div>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user