sections!
This commit is contained in:
142
app.py
142
app.py
@@ -53,6 +53,15 @@ class Product(db.Model):
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"Product('{self.name}')"
|
return f"Product('{self.name}')"
|
||||||
|
|
||||||
|
class Section(db.Model):
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
name = db.Column(db.String(50), nullable=False, unique=True)
|
||||||
|
description = db.Column(db.Text, nullable=True)
|
||||||
|
icon = db.Column(db.String(200), nullable=True)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"Section('{self.name}')"
|
||||||
|
|
||||||
class Plant(db.Model):
|
class Plant(db.Model):
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
name = db.Column(db.String(100), nullable=False)
|
name = db.Column(db.String(100), nullable=False)
|
||||||
@@ -64,6 +73,7 @@ class Plant(db.Model):
|
|||||||
size_id = db.Column(db.Integer, db.ForeignKey('size.id'), nullable=True)
|
size_id = db.Column(db.Integer, db.ForeignKey('size.id'), nullable=True)
|
||||||
care_difficulty_id = db.Column(db.Integer, db.ForeignKey('care_difficulty.id'), nullable=True)
|
care_difficulty_id = db.Column(db.Integer, db.ForeignKey('care_difficulty.id'), nullable=True)
|
||||||
growth_rate_id = db.Column(db.Integer, db.ForeignKey('growth_rate.id'), nullable=True)
|
growth_rate_id = db.Column(db.Integer, db.ForeignKey('growth_rate.id'), nullable=True)
|
||||||
|
section_id = db.Column(db.Integer, db.ForeignKey('section.id'), nullable=True)
|
||||||
products = db.Column(db.Text, nullable=True) # Will store product IDs as comma-separated values
|
products = db.Column(db.Text, nullable=True) # Will store product IDs as comma-separated values
|
||||||
description = db.Column(db.Text, nullable=True)
|
description = db.Column(db.Text, nullable=True)
|
||||||
date_added = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
|
date_added = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
|
||||||
@@ -76,6 +86,7 @@ class Plant(db.Model):
|
|||||||
size = db.relationship('Size', backref='plant_size')
|
size = db.relationship('Size', backref='plant_size')
|
||||||
care_difficulty = db.relationship('CareDifficulty', backref='plant_care_difficulty')
|
care_difficulty = db.relationship('CareDifficulty', backref='plant_care_difficulty')
|
||||||
growth_rate = db.relationship('GrowthRate', backref='plant_growth_rate')
|
growth_rate = db.relationship('GrowthRate', backref='plant_growth_rate')
|
||||||
|
section = db.relationship('Section', backref='plants')
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"Plant('{self.name}', '{self.date_added}')"
|
return f"Plant('{self.name}', '{self.date_added}')"
|
||||||
@@ -140,13 +151,15 @@ def inject_admin_counts():
|
|||||||
climate_count = Climate.query.count()
|
climate_count = Climate.query.count()
|
||||||
product_count = Product.query.count()
|
product_count = Product.query.count()
|
||||||
plant_count = Plant.query.count()
|
plant_count = Plant.query.count()
|
||||||
|
section_count = Section.query.count()
|
||||||
except Exception:
|
except Exception:
|
||||||
environment_count = climate_count = product_count = plant_count = 0
|
environment_count = climate_count = product_count = plant_count = section_count = 0
|
||||||
return dict(
|
return dict(
|
||||||
environment_count=environment_count,
|
environment_count=environment_count,
|
||||||
climate_count=climate_count,
|
climate_count=climate_count,
|
||||||
product_count=product_count,
|
product_count=product_count,
|
||||||
plant_count=plant_count
|
plant_count=plant_count,
|
||||||
|
section_count=section_count
|
||||||
)
|
)
|
||||||
|
|
||||||
def none_if_empty(val):
|
def none_if_empty(val):
|
||||||
@@ -1126,6 +1139,91 @@ def delete_growth_rate(rate_id):
|
|||||||
flash('Growth rate category deleted successfully!', 'success')
|
flash('Growth rate category deleted successfully!', 'success')
|
||||||
return redirect(url_for('manage_growth_rates'))
|
return redirect(url_for('manage_growth_rates'))
|
||||||
|
|
||||||
|
# Section management routes
|
||||||
|
@app.route('/admin/sections', methods=['GET', 'POST'])
|
||||||
|
def manage_sections():
|
||||||
|
if not is_logged_in():
|
||||||
|
return redirect(url_for('login'))
|
||||||
|
if request.method == 'POST':
|
||||||
|
name = request.form['name']
|
||||||
|
description = request.form['description']
|
||||||
|
icon_file = request.files.get('icon')
|
||||||
|
icon_filename = None
|
||||||
|
if not name:
|
||||||
|
flash('Name is required!', 'danger')
|
||||||
|
print('No name provided')
|
||||||
|
return redirect(url_for('manage_sections'))
|
||||||
|
if Section.query.filter_by(name=name).first():
|
||||||
|
flash('Section with this name already exists!', 'danger')
|
||||||
|
print('Duplicate section name')
|
||||||
|
return redirect(url_for('manage_sections'))
|
||||||
|
if icon_file and icon_file.filename:
|
||||||
|
icon_filename = secure_filename(icon_file.filename)
|
||||||
|
icon_path = os.path.join('static/icons', icon_filename)
|
||||||
|
os.makedirs('static/icons', exist_ok=True)
|
||||||
|
try:
|
||||||
|
icon_file.save(icon_path)
|
||||||
|
except Exception as e:
|
||||||
|
print('Error saving icon:', e)
|
||||||
|
flash(f'Error saving icon: {e}', 'danger')
|
||||||
|
try:
|
||||||
|
section = Section(name=name, description=description, icon=icon_filename)
|
||||||
|
db.session.add(section)
|
||||||
|
db.session.commit()
|
||||||
|
flash('Section added successfully!', 'success')
|
||||||
|
print('Section added:', name)
|
||||||
|
except Exception as e:
|
||||||
|
db.session.rollback()
|
||||||
|
print('Error adding section:', e)
|
||||||
|
flash(f'Error adding section: {e}', 'danger')
|
||||||
|
return redirect(url_for('manage_sections'))
|
||||||
|
sections = Section.query.all()
|
||||||
|
return render_template('manage_sections.html',
|
||||||
|
sections=sections,
|
||||||
|
plant_count=len(Plant.query.all()),
|
||||||
|
climate_count=len(Climate.query.all()),
|
||||||
|
environment_count=len(Environment.query.all()),
|
||||||
|
product_count=len(Product.query.all()),
|
||||||
|
light_count=len(Light.query.all()),
|
||||||
|
toxicity_count=len(Toxicity.query.all()),
|
||||||
|
size_count=len(Size.query.all()),
|
||||||
|
difficulty_count=len(CareDifficulty.query.all()),
|
||||||
|
rate_count=len(GrowthRate.query.all()),
|
||||||
|
section_count=len(sections))
|
||||||
|
|
||||||
|
@app.route('/admin/sections/edit/<int:section_id>', methods=['GET', 'POST'])
|
||||||
|
def edit_section(section_id):
|
||||||
|
if not is_logged_in():
|
||||||
|
return redirect(url_for('login'))
|
||||||
|
section = Section.query.get_or_404(section_id)
|
||||||
|
if request.method == 'POST':
|
||||||
|
section.name = request.form['name']
|
||||||
|
section.description = request.form['description']
|
||||||
|
icon_file = request.files.get('icon')
|
||||||
|
if icon_file and icon_file.filename:
|
||||||
|
icon_filename = secure_filename(icon_file.filename)
|
||||||
|
icon_path = os.path.join('static/icons', icon_filename)
|
||||||
|
os.makedirs('static/icons', exist_ok=True)
|
||||||
|
try:
|
||||||
|
icon_file.save(icon_path)
|
||||||
|
except Exception as e:
|
||||||
|
print('Error saving icon:', e)
|
||||||
|
section.icon = icon_filename
|
||||||
|
db.session.commit()
|
||||||
|
flash('Section updated successfully!', 'success')
|
||||||
|
return redirect(url_for('manage_sections'))
|
||||||
|
return render_template('edit_section.html', section=section)
|
||||||
|
|
||||||
|
@app.route('/admin/sections/delete/<int:section_id>', methods=['POST'])
|
||||||
|
def delete_section(section_id):
|
||||||
|
if not is_logged_in():
|
||||||
|
return redirect(url_for('login'))
|
||||||
|
section = Section.query.get_or_404(section_id)
|
||||||
|
db.session.delete(section)
|
||||||
|
db.session.commit()
|
||||||
|
flash('Section deleted successfully!', 'success')
|
||||||
|
return redirect(url_for('manage_sections'))
|
||||||
|
|
||||||
def seed_db():
|
def seed_db():
|
||||||
# Environments
|
# Environments
|
||||||
environments = [
|
environments = [
|
||||||
@@ -1137,6 +1235,18 @@ def seed_db():
|
|||||||
if not Environment.query.filter_by(name=env['name']).first():
|
if not Environment.query.filter_by(name=env['name']).first():
|
||||||
db.session.add(Environment(name=env['name'], description=env['description']))
|
db.session.add(Environment(name=env['name'], description=env['description']))
|
||||||
|
|
||||||
|
# Sections
|
||||||
|
sections = [
|
||||||
|
{'name': 'Succulents', 'description': 'Plants that store water in their leaves, stems, or roots.'},
|
||||||
|
{'name': 'Tropical', 'description': 'Plants native to tropical regions.'},
|
||||||
|
{'name': 'Herbs', 'description': 'Plants used for culinary, medicinal, or aromatic purposes.'},
|
||||||
|
{'name': 'Flowering', 'description': 'Plants grown primarily for their flowers.'},
|
||||||
|
{'name': 'Foliage', 'description': 'Plants grown primarily for their attractive leaves.'}
|
||||||
|
]
|
||||||
|
for sec in sections:
|
||||||
|
if not Section.query.filter_by(name=sec['name']).first():
|
||||||
|
db.session.add(Section(name=sec['name'], description=sec['description']))
|
||||||
|
|
||||||
# Climates
|
# Climates
|
||||||
climates = [
|
climates = [
|
||||||
{'name': 'Tropical', 'description': 'Warm and humid year-round.'},
|
{'name': 'Tropical', 'description': 'Warm and humid year-round.'},
|
||||||
@@ -1233,57 +1343,64 @@ def seed_db():
|
|||||||
medium = Size.query.filter_by(name='Medium').first()
|
medium = Size.query.filter_by(name='Medium').first()
|
||||||
easy = CareDifficulty.query.filter_by(name='Easy').first()
|
easy = CareDifficulty.query.filter_by(name='Easy').first()
|
||||||
moderate = GrowthRate.query.filter_by(name='Moderate').first()
|
moderate = GrowthRate.query.filter_by(name='Moderate').first()
|
||||||
|
|
||||||
|
# Get section instances
|
||||||
|
succulents = Section.query.filter_by(name='Succulents').first()
|
||||||
|
tropical_section = Section.query.filter_by(name='Tropical').first()
|
||||||
|
herbs = Section.query.filter_by(name='Herbs').first()
|
||||||
|
flowering = Section.query.filter_by(name='Flowering').first()
|
||||||
|
foliage = Section.query.filter_by(name='Foliage').first()
|
||||||
|
|
||||||
# 10 example plants
|
# 10 example plants
|
||||||
seed_plants = [
|
seed_plants = [
|
||||||
dict(name='Monstera Deliciosa', climate=tropical, environment=indoor,
|
dict(name='Monstera Deliciosa', climate=tropical, environment=indoor,
|
||||||
light=bright_indirect, toxicity=non_toxic, size=medium,
|
light=bright_indirect, toxicity=non_toxic, size=medium,
|
||||||
care_difficulty=easy, growth_rate=moderate,
|
care_difficulty=easy, growth_rate=moderate, section=tropical_section,
|
||||||
products=[soil, fert], description='A popular tropical houseplant with large, split leaves.',
|
products=[soil, fert], description='A popular tropical houseplant with large, split leaves.',
|
||||||
care_guide='<ul><li>Water when the top 2 inches of soil are dry.</li><li>Provide bright, indirect light.</li><li>Fertilize monthly during growing season.</li></ul>'),
|
care_guide='<ul><li>Water when the top 2 inches of soil are dry.</li><li>Provide bright, indirect light.</li><li>Fertilize monthly during growing season.</li></ul>'),
|
||||||
dict(name='Aloe Vera', climate=arid, environment=indoor,
|
dict(name='Aloe Vera', climate=arid, environment=indoor,
|
||||||
light=bright_indirect, toxicity=non_toxic, size=medium,
|
light=bright_indirect, toxicity=non_toxic, size=medium,
|
||||||
care_difficulty=easy, growth_rate=moderate,
|
care_difficulty=easy, growth_rate=moderate, section=succulents,
|
||||||
products=[soil], description='A succulent known for its medicinal properties.',
|
products=[soil], description='A succulent known for its medicinal properties.',
|
||||||
care_guide='<ul><li>Allow soil to dry completely between waterings.</li><li>Place in bright, indirect sunlight.</li><li>Use well-draining soil.</li></ul>'),
|
care_guide='<ul><li>Allow soil to dry completely between waterings.</li><li>Place in bright, indirect sunlight.</li><li>Use well-draining soil.</li></ul>'),
|
||||||
dict(name='Fiddle Leaf Fig', climate=tropical, environment=indoor,
|
dict(name='Fiddle Leaf Fig', climate=tropical, environment=indoor,
|
||||||
light=bright_indirect, toxicity=non_toxic, size=medium,
|
light=bright_indirect, toxicity=non_toxic, size=medium,
|
||||||
care_difficulty=moderate, growth_rate=moderate,
|
care_difficulty=moderate, growth_rate=moderate, section=foliage,
|
||||||
products=[soil, fert, can], description='A trendy houseplant with large, violin-shaped leaves.',
|
products=[soil, fert, can], description='A trendy houseplant with large, violin-shaped leaves.',
|
||||||
care_guide='<ul><li>Keep soil consistently moist but not soggy.</li><li>Needs bright, filtered light.</li><li>Rotate plant for even growth.</li></ul>'),
|
care_guide='<ul><li>Keep soil consistently moist but not soggy.</li><li>Needs bright, filtered light.</li><li>Rotate plant for even growth.</li></ul>'),
|
||||||
dict(name='Snake Plant', climate=arid, environment=indoor,
|
dict(name='Snake Plant', climate=arid, environment=indoor,
|
||||||
light=bright_indirect, toxicity=non_toxic, size=medium,
|
light=bright_indirect, toxicity=non_toxic, size=medium,
|
||||||
care_difficulty=easy, growth_rate=moderate,
|
care_difficulty=easy, growth_rate=moderate, section=foliage,
|
||||||
products=[soil, can], description='A hardy plant that tolerates low light and irregular watering.',
|
products=[soil, can], description='A hardy plant that tolerates low light and irregular watering.',
|
||||||
care_guide='<ul><li>Water sparingly; let soil dry out between waterings.</li><li>Tolerates low to bright light.</li><li>Wipe leaves to remove dust.</li></ul>'),
|
care_guide='<ul><li>Water sparingly; let soil dry out between waterings.</li><li>Tolerates low to bright light.</li><li>Wipe leaves to remove dust.</li></ul>'),
|
||||||
dict(name='Spider Plant', climate=temperate, environment=indoor,
|
dict(name='Spider Plant', climate=temperate, environment=indoor,
|
||||||
light=bright_indirect, toxicity=non_toxic, size=medium,
|
light=bright_indirect, toxicity=non_toxic, size=medium,
|
||||||
care_difficulty=easy, growth_rate=moderate,
|
care_difficulty=easy, growth_rate=moderate, section=foliage,
|
||||||
products=[soil, can], description='An easy-care plant with arching leaves and baby plantlets.',
|
products=[soil, can], description='An easy-care plant with arching leaves and baby plantlets.',
|
||||||
care_guide='<ul><li>Keep soil slightly moist.</li><li>Thrives in bright, indirect light.</li><li>Trim brown tips as needed.</li></ul>'),
|
care_guide='<ul><li>Keep soil slightly moist.</li><li>Thrives in bright, indirect light.</li><li>Trim brown tips as needed.</li></ul>'),
|
||||||
dict(name='Peace Lily', climate=tropical, environment=indoor,
|
dict(name='Peace Lily', climate=tropical, environment=indoor,
|
||||||
light=bright_indirect, toxicity=non_toxic, size=medium,
|
light=bright_indirect, toxicity=non_toxic, size=medium,
|
||||||
care_difficulty=easy, growth_rate=moderate,
|
care_difficulty=easy, growth_rate=moderate, section=flowering,
|
||||||
products=[soil, fert, can], description='A flowering plant that thrives in shade and purifies air.',
|
products=[soil, fert, can], description='A flowering plant that thrives in shade and purifies air.',
|
||||||
care_guide='<ul><li>Water when leaves droop slightly.</li><li>Prefers low to medium light.</li><li>Remove spent flowers to encourage new blooms.</li></ul>'),
|
care_guide='<ul><li>Water when leaves droop slightly.</li><li>Prefers low to medium light.</li><li>Remove spent flowers to encourage new blooms.</li></ul>'),
|
||||||
dict(name='Jade Plant', climate=arid, environment=indoor,
|
dict(name='Jade Plant', climate=arid, environment=indoor,
|
||||||
light=bright_indirect, toxicity=non_toxic, size=medium,
|
light=bright_indirect, toxicity=non_toxic, size=medium,
|
||||||
care_difficulty=easy, growth_rate=moderate,
|
care_difficulty=easy, growth_rate=moderate, section=succulents,
|
||||||
products=[soil], description='A succulent with thick, shiny leaves and a tree-like form.',
|
products=[soil], description='A succulent with thick, shiny leaves and a tree-like form.',
|
||||||
care_guide='<ul><li>Let soil dry between waterings.</li><li>Needs several hours of direct sunlight.</li><li>Prune to maintain shape.</li></ul>'),
|
care_guide='<ul><li>Let soil dry between waterings.</li><li>Needs several hours of direct sunlight.</li><li>Prune to maintain shape.</li></ul>'),
|
||||||
dict(name='Tomato', climate=temperate, environment=outdoor,
|
dict(name='Tomato', climate=temperate, environment=outdoor,
|
||||||
light=bright_indirect, toxicity=non_toxic, size=medium,
|
light=bright_indirect, toxicity=non_toxic, size=medium,
|
||||||
care_difficulty=moderate, growth_rate=moderate,
|
care_difficulty=moderate, growth_rate=moderate, section=herbs,
|
||||||
products=[soil, fert, can], description='A classic edible plant for outdoor gardens.',
|
products=[soil, fert, can], description='A classic edible plant for outdoor gardens.',
|
||||||
care_guide='<ul><li>Water regularly, keeping soil consistently moist.</li><li>Provide full sun.</li><li>Support with stakes or cages.</li></ul>'),
|
care_guide='<ul><li>Water regularly, keeping soil consistently moist.</li><li>Provide full sun.</li><li>Support with stakes or cages.</li></ul>'),
|
||||||
dict(name='Basil', climate=mediterranean, environment=greenhouse,
|
dict(name='Basil', climate=mediterranean, environment=greenhouse,
|
||||||
light=bright_indirect, toxicity=non_toxic, size=medium,
|
light=bright_indirect, toxicity=non_toxic, size=medium,
|
||||||
care_difficulty=easy, growth_rate=moderate,
|
care_difficulty=easy, growth_rate=moderate, section=herbs,
|
||||||
products=[soil, fert, light], description='A fragrant herb often grown in greenhouses or sunny windows.',
|
products=[soil, fert, light], description='A fragrant herb often grown in greenhouses or sunny windows.',
|
||||||
care_guide='<ul><li>Water when soil surface is dry.</li><li>Needs at least 6 hours of sunlight daily.</li><li>Pinch off flowers to encourage leaf growth.</li></ul>'),
|
care_guide='<ul><li>Water when soil surface is dry.</li><li>Needs at least 6 hours of sunlight daily.</li><li>Pinch off flowers to encourage leaf growth.</li></ul>'),
|
||||||
dict(name='Cactus', climate=arid, environment=indoor,
|
dict(name='Cactus', climate=arid, environment=indoor,
|
||||||
light=bright_indirect, toxicity=non_toxic, size=medium,
|
light=bright_indirect, toxicity=non_toxic, size=medium,
|
||||||
care_difficulty=easy, growth_rate=moderate,
|
care_difficulty=easy, growth_rate=moderate, section=succulents,
|
||||||
products=[soil, light], description='A spiny plant adapted to dry, sunny conditions.',
|
products=[soil, light], description='A spiny plant adapted to dry, sunny conditions.',
|
||||||
care_guide='<ul><li>Water sparingly, especially in winter.</li><li>Place in bright, direct sunlight.</li><li>Use cactus-specific soil mix.</li></ul>'),
|
care_guide='<ul><li>Water sparingly, especially in winter.</li><li>Place in bright, direct sunlight.</li><li>Use cactus-specific soil mix.</li></ul>'),
|
||||||
]
|
]
|
||||||
@@ -1297,6 +1414,7 @@ def seed_db():
|
|||||||
size_id=plant['size'].id if plant['size'] else None,
|
size_id=plant['size'].id if plant['size'] else None,
|
||||||
care_difficulty_id=plant['care_difficulty'].id if plant['care_difficulty'] else None,
|
care_difficulty_id=plant['care_difficulty'].id if plant['care_difficulty'] else None,
|
||||||
growth_rate_id=plant['growth_rate'].id if plant['growth_rate'] else None,
|
growth_rate_id=plant['growth_rate'].id if plant['growth_rate'] else None,
|
||||||
|
section_id=plant['section'].id if plant['section'] else None,
|
||||||
products=','.join(str(p.id) for p in plant['products'] if p),
|
products=','.join(str(p.id) for p in plant['products'] if p),
|
||||||
description=plant['description'],
|
description=plant['description'],
|
||||||
care_guide=plant['care_guide']
|
care_guide=plant['care_guide']
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
"""Add Section model and relationship to Plant
|
||||||
|
|
||||||
|
Revision ID: f746ca4a01f7
|
||||||
|
Revises: f83d55cc5aa7
|
||||||
|
Create Date: 2025-06-08 17:00:55.885897
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'f746ca4a01f7'
|
||||||
|
down_revision = 'f83d55cc5aa7'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
with op.batch_alter_table('plant', schema=None) as batch_op:
|
||||||
|
batch_op.add_column(sa.Column('section_id', sa.Integer(), nullable=True))
|
||||||
|
batch_op.create_foreign_key(None, 'section', ['section_id'], ['id'])
|
||||||
|
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
with op.batch_alter_table('plant', schema=None) as batch_op:
|
||||||
|
batch_op.drop_constraint(None, type_='foreignkey')
|
||||||
|
batch_op.drop_column('section_id')
|
||||||
|
|
||||||
|
# ### end Alembic commands ###
|
||||||
@@ -95,6 +95,15 @@
|
|||||||
</div>
|
</div>
|
||||||
<span class="badge-product text-xs font-semibold px-2 py-0.5 rounded">{{ product_count }}</span>
|
<span class="badge-product text-xs font-semibold px-2 py-0.5 rounded">{{ product_count }}</span>
|
||||||
</a>
|
</a>
|
||||||
|
<a href="{{ url_for('manage_sections') }}" class="nav-sections flex items-center justify-between p-4 rounded-lg transition-colors hover:bg-[#e6f0f7]">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v18m9-9H3" />
|
||||||
|
</svg>
|
||||||
|
<span class="font-medium">Sections</span>
|
||||||
|
</div>
|
||||||
|
<span class="badge-section text-xs font-semibold px-2 py-0.5 rounded">{{ section_count }}</span>
|
||||||
|
</a>
|
||||||
</nav>
|
</nav>
|
||||||
<!-- Only admin content is inside the background wrapper now -->
|
<!-- Only admin content is inside the background wrapper now -->
|
||||||
<div class="bg-[#f5f7f2] shadow-lg rounded-xl p-8 mb-6">
|
<div class="bg-[#f5f7f2] shadow-lg rounded-xl p-8 mb-6">
|
||||||
|
|||||||
@@ -14,8 +14,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="picture" class="block text-sm font-semibold text-gray-700 mb-1">Picture</label>
|
<label for="picture" class="block text-sm font-semibold text-gray-700 mb-1">Picture</label>
|
||||||
<input type="file" name="picture" id="picture"
|
<input type="file" name="picture" id="picture" accept="image/*"
|
||||||
class="mt-1 block w-full text-sm text-gray-700 border border-gray-300 rounded-lg px-3 py-2 bg-gray-50 focus:outline-none focus:ring-2 focus:ring-blue-500">
|
class="mt-1 block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-md file:border-0 file:text-sm file:font-semibold file:bg-[#6b8f71] file:text-white hover:file:bg-[#5a7b5f]">
|
||||||
</div>
|
</div>
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -18,7 +18,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="icon" class="block text-sm font-medium text-gray-700">Icon (SVG)</label>
|
<label for="icon" class="block text-sm font-medium text-gray-700">Icon (SVG)</label>
|
||||||
<input type="file" name="icon" id="icon" accept=".svg" class="mt-1 block w-full text-sm text-gray-700">
|
<input type="file" name="icon" id="icon" accept=".svg"
|
||||||
|
class="mt-1 block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-md file:border-0 file:text-sm file:font-semibold file:bg-[#6b8f71] file:text-white hover:file:bg-[#5a7b5f]">
|
||||||
{% if difficulty.icon %}
|
{% if difficulty.icon %}
|
||||||
<div class="mt-2">
|
<div class="mt-2">
|
||||||
<span class="text-xs text-gray-500">Current icon:</span>
|
<span class="text-xs text-gray-500">Current icon:</span>
|
||||||
|
|||||||
@@ -18,15 +18,13 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="icon" class="block text-sm font-medium text-gray-700">Icon (SVG)</label>
|
<label for="icon" class="block text-sm font-medium text-gray-700">Icon (SVG)</label>
|
||||||
<input type="file" name="icon" id="icon" accept=".svg" class="mt-1 block w-full text-sm text-gray-700">
|
<input type="file" name="icon" id="icon" accept=".svg"
|
||||||
|
class="mt-1 block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-md file:border-0 file:text-sm file:font-semibold file:bg-[#6b8f71] file:text-white hover:file:bg-[#5a7b5f]">
|
||||||
{% if climate.icon %}
|
{% if climate.icon %}
|
||||||
<img src="{{ url_for('static', filename='icons/' ~ climate.icon) }}" alt="Icon" class="w-8 h-8 mt-2">
|
<img src="{{ url_for('static', filename='icons/' ~ climate.icon) }}" alt="Icon" class="w-8 h-8 mt-2">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<button type="submit"
|
<button type="submit" class="btn-main w-full">Save Changes</button>
|
||||||
class="w-full bg-blue-500 text-white py-2 px-4 rounded-md hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2">
|
|
||||||
Save Changes
|
|
||||||
</button>
|
|
||||||
<a href="{{ url_for('manage_climates') }}" class="block text-center mt-4 text-gray-500 hover:text-gray-700">Cancel</a>
|
<a href="{{ url_for('manage_climates') }}" class="block text-center mt-4 text-gray-500 hover:text-gray-700">Cancel</a>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -23,10 +23,7 @@
|
|||||||
<img src="{{ url_for('static', filename='icons/' ~ environment.icon) }}" alt="Icon" class="w-8 h-8 mt-2">
|
<img src="{{ url_for('static', filename='icons/' ~ environment.icon) }}" alt="Icon" class="w-8 h-8 mt-2">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<button type="submit"
|
<button type="submit" class="btn-main w-full">Save Changes</button>
|
||||||
class="w-full bg-blue-500 text-white py-2 px-4 rounded-md hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2">
|
|
||||||
Save Changes
|
|
||||||
</button>
|
|
||||||
<a href="{{ url_for('manage_environments') }}" class="block text-center mt-4 text-gray-500 hover:text-gray-700">Cancel</a>
|
<a href="{{ url_for('manage_environments') }}" class="block text-center mt-4 text-gray-500 hover:text-gray-700">Cancel</a>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -18,7 +18,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="icon" class="block text-sm font-medium text-gray-700">Icon (SVG)</label>
|
<label for="icon" class="block text-sm font-medium text-gray-700">Icon (SVG)</label>
|
||||||
<input type="file" name="icon" id="icon" accept=".svg" class="mt-1 block w-full text-sm text-gray-700">
|
<input type="file" name="icon" id="icon" accept=".svg"
|
||||||
|
class="mt-1 block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-md file:border-0 file:text-sm file:font-semibold file:bg-[#6b8f71] file:text-white hover:file:bg-[#5a7b5f]">
|
||||||
{% if rate.icon %}
|
{% if rate.icon %}
|
||||||
<div class="mt-2">
|
<div class="mt-2">
|
||||||
<span class="text-xs text-gray-500">Current icon:</span>
|
<span class="text-xs text-gray-500">Current icon:</span>
|
||||||
@@ -26,7 +27,10 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="btn-main w-full">Save Changes</button>
|
<button type="submit"
|
||||||
|
class="w-full bg-blue-500 text-white py-2 px-4 rounded-md hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2">
|
||||||
|
Save Changes
|
||||||
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -18,7 +18,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="icon" class="block text-sm font-medium text-gray-700">Icon (SVG)</label>
|
<label for="icon" class="block text-sm font-medium text-gray-700">Icon (SVG)</label>
|
||||||
<input type="file" name="icon" id="icon" accept=".svg" class="mt-1 block w-full text-sm text-gray-700">
|
<input type="file" name="icon" id="icon" accept=".svg"
|
||||||
|
class="mt-1 block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-md file:border-0 file:text-sm file:font-semibold file:bg-[#6b8f71] file:text-white hover:file:bg-[#5a7b5f]">
|
||||||
{% if light.icon %}
|
{% if light.icon %}
|
||||||
<div class="mt-2">
|
<div class="mt-2">
|
||||||
<span class="text-xs text-gray-500">Current icon:</span>
|
<span class="text-xs text-gray-500">Current icon:</span>
|
||||||
@@ -26,7 +27,10 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="btn-main w-full">Save Changes</button>
|
<button type="submit"
|
||||||
|
class="w-full bg-blue-500 text-white py-2 px-4 rounded-md hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2">
|
||||||
|
Save Changes
|
||||||
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -14,8 +14,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="picture" class="block text-sm font-semibold text-gray-700 mb-1">Picture</label>
|
<label for="picture" class="block text-sm font-semibold text-gray-700 mb-1">Picture</label>
|
||||||
<input type="file" name="picture" id="picture"
|
<input type="file" name="picture" id="picture" accept="image/*"
|
||||||
class="mt-1 block w-full text-sm text-gray-700 border border-gray-300 rounded-lg px-3 py-2 bg-gray-50 focus:outline-none focus:ring-2 focus:ring-blue-500">
|
class="mt-1 block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-md file:border-0 file:text-sm file:font-semibold file:bg-[#6b8f71] file:text-white hover:file:bg-[#5a7b5f]">
|
||||||
{% if plant.picture %}
|
{% if plant.picture %}
|
||||||
<img src="{{ url_for('static', filename='uploads/' ~ plant.picture) }}" alt="{{ plant.name }}" class="w-24 h-24 object-cover rounded mt-2">
|
<img src="{{ url_for('static', filename='uploads/' ~ plant.picture) }}" alt="{{ plant.name }}" class="w-24 h-24 object-cover rounded mt-2">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -108,7 +108,10 @@
|
|||||||
<div id="quill-care-guide" class="bg-white rounded border border-gray-300" style="min-height: 120px;">{{ plant.care_guide|safe }}</div>
|
<div id="quill-care-guide" class="bg-white rounded border border-gray-300" style="min-height: 120px;">{{ plant.care_guide|safe }}</div>
|
||||||
<textarea name="care_guide" id="care_guide" style="display:none;">{{ plant.care_guide }}</textarea>
|
<textarea name="care_guide" id="care_guide" style="display:none;">{{ plant.care_guide }}</textarea>
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="w-full btn-main text-lg font-semibold">Save Changes</button>
|
<button type="submit"
|
||||||
|
class="w-full bg-blue-500 text-white py-2 px-4 rounded-md hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2">
|
||||||
|
Save Changes
|
||||||
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -16,10 +16,7 @@
|
|||||||
<textarea name="description" id="description" rows="3"
|
<textarea name="description" id="description" rows="3"
|
||||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">{{ product.description }}</textarea>
|
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">{{ product.description }}</textarea>
|
||||||
</div>
|
</div>
|
||||||
<button type="submit"
|
<button type="submit" class="btn-main w-full">Save Changes</button>
|
||||||
class="w-full bg-blue-500 text-white py-2 px-4 rounded-md hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2">
|
|
||||||
Save Changes
|
|
||||||
</button>
|
|
||||||
<a href="{{ url_for('manage_products') }}" class="block text-center mt-4 text-gray-500 hover:text-gray-700">Cancel</a>
|
<a href="{{ url_for('manage_products') }}" class="block text-center mt-4 text-gray-500 hover:text-gray-700">Cancel</a>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
34
templates/edit_section.html
Normal file
34
templates/edit_section.html
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
{% extends "admin_base.html" %}
|
||||||
|
|
||||||
|
{% block title %}Edit Section{% endblock %}
|
||||||
|
|
||||||
|
{% block admin_content %}
|
||||||
|
<div class="max-w-xl mx-auto bg-white p-8 rounded-lg shadow-md">
|
||||||
|
<h1 class="text-2xl font-bold mb-6">Edit Section</h1>
|
||||||
|
<form method="POST" enctype="multipart/form-data" class="space-y-4">
|
||||||
|
<div>
|
||||||
|
<label for="name" class="block text-sm font-medium text-gray-700">Name</label>
|
||||||
|
<input type="text" name="name" id="name" value="{{ section.name }}" required
|
||||||
|
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="description" class="block text-sm font-medium text-gray-700">Description</label>
|
||||||
|
<textarea name="description" id="description" rows="3"
|
||||||
|
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">{{ section.description }}</textarea>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="icon" class="block text-sm font-medium text-gray-700">Icon</label>
|
||||||
|
{% if section.icon %}
|
||||||
|
<div class="mb-2">
|
||||||
|
<img src="{{ url_for('static', filename='icons/' + section.icon) }}" alt="{{ section.name }}" class="h-8 w-8 object-contain">
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<input type="file" name="icon" id="icon" accept="image/*"
|
||||||
|
class="mt-1 block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-md file:border-0 file:text-sm file:font-semibold file:bg-[#6b8f71] file:text-white hover:file:bg-[#5a7b5f]">
|
||||||
|
<p class="mt-1 text-sm text-gray-500">Leave empty to keep the current icon</p>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn-main w-full">Save Changes</button>
|
||||||
|
<a href="{{ url_for('manage_sections') }}" class="block text-center mt-4 text-gray-500 hover:text-gray-700">Cancel</a>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
@@ -18,7 +18,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="icon" class="block text-sm font-medium text-gray-700">Icon (SVG)</label>
|
<label for="icon" class="block text-sm font-medium text-gray-700">Icon (SVG)</label>
|
||||||
<input type="file" name="icon" id="icon" accept=".svg" class="mt-1 block w-full text-sm text-gray-700">
|
<input type="file" name="icon" id="icon" accept=".svg"
|
||||||
|
class="mt-1 block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-md file:border-0 file:text-sm file:font-semibold file:bg-[#6b8f71] file:text-white hover:file:bg-[#5a7b5f]">
|
||||||
{% if size.icon %}
|
{% if size.icon %}
|
||||||
<div class="mt-2">
|
<div class="mt-2">
|
||||||
<span class="text-xs text-gray-500">Current icon:</span>
|
<span class="text-xs text-gray-500">Current icon:</span>
|
||||||
@@ -26,7 +27,10 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="btn-main w-full">Save Changes</button>
|
<button type="submit"
|
||||||
|
class="w-full bg-blue-500 text-white py-2 px-4 rounded-md hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2">
|
||||||
|
Save Changes
|
||||||
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -18,7 +18,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="icon" class="block text-sm font-medium text-gray-700">Icon (SVG)</label>
|
<label for="icon" class="block text-sm font-medium text-gray-700">Icon (SVG)</label>
|
||||||
<input type="file" name="icon" id="icon" accept=".svg" class="mt-1 block w-full text-sm text-gray-700">
|
<input type="file" name="icon" id="icon" accept=".svg"
|
||||||
|
class="mt-1 block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-md file:border-0 file:text-sm file:font-semibold file:bg-[#6b8f71] file:text-white hover:file:bg-[#5a7b5f]">
|
||||||
{% if toxicity.icon %}
|
{% if toxicity.icon %}
|
||||||
<div class="mt-2">
|
<div class="mt-2">
|
||||||
<span class="text-xs text-gray-500">Current icon:</span>
|
<span class="text-xs text-gray-500">Current icon:</span>
|
||||||
@@ -26,7 +27,10 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="btn-main w-full">Save Changes</button>
|
<button type="submit"
|
||||||
|
class="w-full bg-blue-500 text-white py-2 px-4 rounded-md hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2">
|
||||||
|
Save Changes
|
||||||
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -20,7 +20,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="icon" class="block text-sm font-medium text-gray-700">Icon (SVG)</label>
|
<label for="icon" class="block text-sm font-medium text-gray-700">Icon (SVG)</label>
|
||||||
<input type="file" name="icon" id="icon" accept=".svg" class="mt-1 block w-full text-sm text-gray-700">
|
<input type="file" name="icon" id="icon" accept=".svg"
|
||||||
|
class="mt-1 block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-md file:border-0 file:text-sm file:font-semibold file:bg-[#6b8f71] file:text-white hover:file:bg-[#5a7b5f]">
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="w-full btn-main text-lg font-semibold">Add Care Difficulty</button>
|
<button type="submit" class="w-full btn-main text-lg font-semibold">Add Care Difficulty</button>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -20,7 +20,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="icon" class="block text-sm font-medium text-gray-700">Icon (SVG)</label>
|
<label for="icon" class="block text-sm font-medium text-gray-700">Icon (SVG)</label>
|
||||||
<input type="file" name="icon" id="icon" accept=".svg" class="mt-1 block w-full text-sm text-gray-700">
|
<input type="file" name="icon" id="icon" accept=".svg"
|
||||||
|
class="mt-1 block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-md file:border-0 file:text-sm file:font-semibold file:bg-[#6b8f71] file:text-white hover:file:bg-[#5a7b5f]">
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="w-full btn-main text-lg font-semibold">Add Climate</button>
|
<button type="submit" class="w-full btn-main text-lg font-semibold">Add Climate</button>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -20,7 +20,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="icon" class="block text-sm font-medium text-gray-700">Icon (SVG)</label>
|
<label for="icon" class="block text-sm font-medium text-gray-700">Icon (SVG)</label>
|
||||||
<input type="file" name="icon" id="icon" accept=".svg" class="mt-1 block w-full text-sm text-gray-700">
|
<input type="file" name="icon" id="icon" accept=".svg"
|
||||||
|
class="mt-1 block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-md file:border-0 file:text-sm file:font-semibold file:bg-[#6b8f71] file:text-white hover:file:bg-[#5a7b5f]">
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="w-full btn-main text-lg font-semibold">Add Environment</button>
|
<button type="submit" class="w-full btn-main text-lg font-semibold">Add Environment</button>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -20,7 +20,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="icon" class="block text-sm font-medium text-gray-700">Icon (SVG)</label>
|
<label for="icon" class="block text-sm font-medium text-gray-700">Icon (SVG)</label>
|
||||||
<input type="file" name="icon" id="icon" accept=".svg" class="mt-1 block w-full text-sm text-gray-700">
|
<input type="file" name="icon" id="icon" accept=".svg"
|
||||||
|
class="mt-1 block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-md file:border-0 file:text-sm file:font-semibold file:bg-[#6b8f71] file:text-white hover:file:bg-[#5a7b5f]">
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="w-full btn-main text-lg font-semibold">Add Growth Rate</button>
|
<button type="submit" class="w-full btn-main text-lg font-semibold">Add Growth Rate</button>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -20,7 +20,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="icon" class="block text-sm font-medium text-gray-700">Icon (SVG)</label>
|
<label for="icon" class="block text-sm font-medium text-gray-700">Icon (SVG)</label>
|
||||||
<input type="file" name="icon" id="icon" accept=".svg" class="mt-1 block w-full text-sm text-gray-700">
|
<input type="file" name="icon" id="icon" accept=".svg"
|
||||||
|
class="mt-1 block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-md file:border-0 file:text-sm file:font-semibold file:bg-[#6b8f71] file:text-white hover:file:bg-[#5a7b5f]">
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="w-full btn-main text-lg font-semibold">Add Light Requirement</button>
|
<button type="submit" class="w-full btn-main text-lg font-semibold">Add Light Requirement</button>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -23,8 +23,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="picture" class="block text-sm font-medium text-gray-700">Picture</label>
|
<label for="picture" class="block text-sm font-medium text-gray-700">Picture</label>
|
||||||
<input type="file" name="picture" id="picture"
|
<input type="file" name="picture" id="picture" accept="image/*"
|
||||||
class="mt-1 block w-full text-sm text-gray-700">
|
class="mt-1 block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-md file:border-0 file:text-sm file:font-semibold file:bg-[#6b8f71] file:text-white hover:file:bg-[#5a7b5f]">
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="climate_id" class="block text-sm font-medium text-gray-700">Climate</label>
|
<label for="climate_id" class="block text-sm font-medium text-gray-700">Climate</label>
|
||||||
|
|||||||
60
templates/manage_sections.html
Normal file
60
templates/manage_sections.html
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
{% extends "admin_base.html" %}
|
||||||
|
|
||||||
|
{% block title %}Manage Sections{% endblock %}
|
||||||
|
|
||||||
|
{% block admin_content %}
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||||
|
<!-- Add new section form -->
|
||||||
|
<div class="bg-gray-50 p-6 rounded-lg">
|
||||||
|
<h2 class="text-xl font-bold mb-4">Add New Section</h2>
|
||||||
|
<form method="POST" enctype="multipart/form-data" class="space-y-4">
|
||||||
|
<div>
|
||||||
|
<label for="name" class="block text-sm font-medium text-gray-700">Name</label>
|
||||||
|
<input type="text" name="name" id="name" required
|
||||||
|
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="description" class="block text-sm font-medium text-gray-700">Description</label>
|
||||||
|
<textarea name="description" id="description" rows="3"
|
||||||
|
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500"></textarea>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="icon" class="block text-sm font-medium text-gray-700">Icon</label>
|
||||||
|
<input type="file" name="icon" id="icon" accept="image/*"
|
||||||
|
class="mt-1 block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-md file:border-0 file:text-sm file:font-semibold file:bg-[#6b8f71] file:text-white hover:file:bg-[#5a7b5f]">
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="w-full btn-main text-lg font-semibold">Add Section</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- List of existing sections -->
|
||||||
|
<div class="bg-gray-50 p-6 rounded-lg">
|
||||||
|
<h2 class="text-xl font-bold mb-4">Existing Sections</h2>
|
||||||
|
<div class="space-y-4">
|
||||||
|
{% for section in sections %}
|
||||||
|
<div class="p-4 rounded-lg shadow flex justify-between items-center">
|
||||||
|
<div class="flex items-center">
|
||||||
|
{% if section.icon %}
|
||||||
|
<img src="{{ url_for('static', filename='icons/' + section.icon) }}" alt="{{ section.name }}" class="h-8 w-8 object-contain mr-3">
|
||||||
|
{% endif %}
|
||||||
|
<div>
|
||||||
|
<h3 class="font-bold">{{ section.name }}</h3>
|
||||||
|
{% if section.description %}
|
||||||
|
<p class="text-gray-600 mt-2">{{ section.description }}</p>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex space-x-2">
|
||||||
|
<a href="{{ url_for('edit_section', section_id=section.id) }}" class="btn-edit">Edit</a>
|
||||||
|
<form method="POST" action="{{ url_for('delete_section', section_id=section.id) }}" onsubmit="return confirm('Are you sure you want to delete this section?');">
|
||||||
|
<button type="submit" class="btn-delete">Delete</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<p class="text-gray-500">No sections added yet.</p>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
@@ -20,7 +20,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="icon" class="block text-sm font-medium text-gray-700">Icon (SVG)</label>
|
<label for="icon" class="block text-sm font-medium text-gray-700">Icon (SVG)</label>
|
||||||
<input type="file" name="icon" id="icon" accept=".svg" class="mt-1 block w-full text-sm text-gray-700">
|
<input type="file" name="icon" id="icon" accept=".svg"
|
||||||
|
class="mt-1 block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-md file:border-0 file:text-sm file:font-semibold file:bg-[#6b8f71] file:text-white hover:file:bg-[#5a7b5f]">
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="w-full btn-main text-lg font-semibold">Add Size Category</button>
|
<button type="submit" class="w-full btn-main text-lg font-semibold">Add Size Category</button>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -20,7 +20,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="icon" class="block text-sm font-medium text-gray-700">Icon (SVG)</label>
|
<label for="icon" class="block text-sm font-medium text-gray-700">Icon (SVG)</label>
|
||||||
<input type="file" name="icon" id="icon" accept=".svg" class="mt-1 block w-full text-sm text-gray-700">
|
<input type="file" name="icon" id="icon" accept=".svg"
|
||||||
|
class="mt-1 block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-md file:border-0 file:text-sm file:font-semibold file:bg-[#6b8f71] file:text-white hover:file:bg-[#5a7b5f]">
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="w-full btn-main text-lg font-semibold">Add Toxicity Level</button>
|
<button type="submit" class="w-full btn-main text-lg font-semibold">Add Toxicity Level</button>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
Reference in New Issue
Block a user