diff --git a/backend/api/management/commands/seed_legacy_flavors.py b/backend/api/management/commands/seed_legacy_flavors.py index ab9e84e..3b26d81 100644 --- a/backend/api/management/commands/seed_legacy_flavors.py +++ b/backend/api/management/commands/seed_legacy_flavors.py @@ -3,8 +3,8 @@ import os import urllib.request from django.core.management.base import BaseCommand from django.core.files import File -from tempfile import NamedTemporaryFile from django.conf import settings +from django.utils.text import slugify from api.models import Category, Flavor class Command(BaseCommand): @@ -14,54 +14,53 @@ class Command(BaseCommand): if not url: return None try: - # Generate a clean, consistent filename - ext = url.split('.')[-1].split('?')[0] - if len(ext) > 4 or len(ext) < 3: ext = 'png' - filename = f"legacy_{flavor_name.replace(' ', '_').lower()}.{ext}" + safe_name = slugify(flavor_name) + ext = url.split('.')[-1].split('?')[0].lower() + if ext not in ['jpg', 'jpeg', 'png', 'webp', 'gif']: + ext = 'png' - # Use a fixed path to check for existing file + filename = f"legacy_{safe_name}.{ext}" filepath = os.path.join(settings.MEDIA_ROOT, 'flavors', filename) + + os.makedirs(os.path.dirname(filepath), exist_ok=True) req = urllib.request.Request(url, headers={'User-Agent': 'Mozilla/5.0'}) - with urllib.request.urlopen(req) as response: - img_temp = NamedTemporaryFile(delete=True) - img_temp.write(response.read()) - img_temp.flush() - img_temp.seek(0) + with urllib.request.urlopen(req, timeout=10) as response: + content = response.read() - # If file exists, delete it so Django doesn't add a suffix - if os.path.exists(filepath): - os.remove(filepath) - - return File(img_temp, name=filename) + if not content: + return None + + if os.path.exists(filepath): + os.remove(filepath) + + with open(filepath, 'wb') as f: + f.write(content) + + return f"flavors/{filename}" except Exception as e: - self.stdout.write(self.style.WARNING(f"Could not download image for {flavor_name}: {e}")) + self.stdout.write(self.style.WARNING(f"Failed to download image for {flavor_name}: {e}")) return None def handle(self, *args, **options): - # 1. Remove old legacy flavors (ones without external_id or marked as legacy) - # To be safe, we only remove those marked as legacy or with no external_id - removed_count, _ = Flavor.objects.filter(is_legacy=True).delete() + # Remove old legacy entries + Flavor.objects.filter(is_legacy=True).delete() Flavor.objects.filter(external_id__isnull=True).delete() - self.stdout.write(self.style.SUCCESS(f"Removed {removed_count} old legacy flavors.")) - # Ensure main categories exist energy = Category.objects.get_or_create(name='Energy', defaults={'slug': 'energy'})[0] hydration = Category.objects.get_or_create(name='Hydration', defaults={'slug': 'hydration'})[0] iced_tea = Category.objects.get_or_create(name='Iced Tea', defaults={'slug': 'iced-tea'})[0] packs = Category.objects.get_or_create(name='Packs and other', defaults={'slug': 'packs-and-other'})[0] - # Try both common locations for the legacy folder legacy_dir = os.path.join(settings.BASE_DIR, 'legacy') if not os.path.exists(legacy_dir): legacy_dir = os.path.join(settings.BASE_DIR, '..', 'legacy') if not os.path.exists(legacy_dir): - self.stdout.write(self.style.ERROR(f"Legacy directory not found. Checked: {os.path.join(settings.BASE_DIR, 'legacy')} and {os.path.join(settings.BASE_DIR, '..', 'legacy')}")) + self.stdout.write(self.style.ERROR(f"Legacy directory not found.")) return json_files = [f for f in os.listdir(legacy_dir) if f.endswith('.json')] - created_count = 0 for json_file in json_files: @@ -78,7 +77,6 @@ class Command(BaseCommand): full_desc = f"**Geschmack:** {taste}\n\n{desc}\n\n**Status:** {status_text}" - # Determine category cat = energy if "hydration" in name.lower() or "hydration" in desc.lower(): cat = hydration @@ -98,12 +96,20 @@ class Command(BaseCommand): ) if image_url: - img_file = self.download_image(image_url, name) - if img_file: - flavor.image.save(img_file.name, img_file, save=False) + # Check if local file exists + file_exists = False + if flavor.image: + abs_path = os.path.join(settings.MEDIA_ROOT, flavor.image.name) + if os.path.exists(abs_path): + file_exists = True + + if not file_exists: + rel_path = self.download_image(image_url, name) + if rel_path: + flavor.image = rel_path flavor.save() created_count += 1 self.stdout.write(f"Added legacy flavor: {name}") - self.stdout.write(self.style.SUCCESS(f"Finished! Created {created_count} legacy flavors from JSON.")) + self.stdout.write(self.style.SUCCESS(f"Finished! Created {created_count} legacy flavors.")) diff --git a/backend/api/management/commands/sync_flavors.py b/backend/api/management/commands/sync_flavors.py index 060daa5..cbb03b7 100644 --- a/backend/api/management/commands/sync_flavors.py +++ b/backend/api/management/commands/sync_flavors.py @@ -5,7 +5,7 @@ import os from django.core.management.base import BaseCommand from django.core.files import File from django.conf import settings -from tempfile import NamedTemporaryFile +from django.utils.text import slugify from api.models import Category, Flavor class Command(BaseCommand): @@ -22,29 +22,32 @@ class Command(BaseCommand): if not url: return None try: - # Generate a clean, consistent filename - ext = url.split('.')[-1].split('?')[0] - if len(ext) > 4 or len(ext) < 3: ext = 'png' - filename = f"{flavor_name.replace(' ', '_').lower()}.{ext}" + safe_name = slugify(flavor_name) + ext = url.split('.')[-1].split('?')[0].lower() + if ext not in ['jpg', 'jpeg', 'png', 'webp', 'gif']: + ext = 'png' - # Use a fixed path to check for existing file + filename = f"{safe_name}.{ext}" filepath = os.path.join(settings.MEDIA_ROOT, 'flavors', filename) - # Download to a temporary file + os.makedirs(os.path.dirname(filepath), exist_ok=True) + req = urllib.request.Request(url, headers={'User-Agent': 'Mozilla/5.0'}) - with urllib.request.urlopen(req) as response: - img_temp = NamedTemporaryFile(delete=True) - img_temp.write(response.read()) - img_temp.flush() - img_temp.seek(0) + with urllib.request.urlopen(req, timeout=10) as response: + content = response.read() - # If file exists, delete it so Django doesn't add a suffix - if os.path.exists(filepath): - os.remove(filepath) - - return File(img_temp, name=filename) + if not content: + return None + + if os.path.exists(filepath): + os.remove(filepath) + + with open(filepath, 'wb') as f: + f.write(content) + + return f"flavors/{filename}" except Exception as e: - self.stdout.write(self.style.WARNING(f"Could not download image for {flavor_name}: {e}")) + self.stdout.write(self.style.WARNING(f"Failed to download image for {flavor_name}: {e}")) return None def handle(self, *args, **options): @@ -62,7 +65,6 @@ class Command(BaseCommand): products = data.get('products', []) self.stdout.write(f"Found {len(products)} products.") - # Ensure categories exist cat_map = { 'energy': Category.objects.get_or_create(name='Energy', defaults={'slug': 'energy'})[0], 'hydration': Category.objects.get_or_create(name='Hydration', defaults={'slug': 'hydration'})[0], @@ -78,12 +80,9 @@ class Command(BaseCommand): for p in products: title = p.get('title') tags = p.get('tags', []) - product_type = p.get('product_type', '').lower() if isinstance(tags, str): tags = [t.strip() for t in tags.split(',')] - # Determine category - category = None tags_lower = [t.lower() for t in tags] title_lower = title.lower() @@ -94,6 +93,7 @@ class Command(BaseCommand): if 'shaker' in title_lower or 'merch' in tags_lower: is_pack = True + category = None if is_pack: category = cat_map['packs'] elif 'holy energy' in tags_lower or 'energy' in tags_lower: @@ -119,51 +119,43 @@ class Command(BaseCommand): handle = p.get('handle') shop_url = f"https://weareholy.com/products/{handle}" if handle else None - # Create or update + # Find or create flavor = Flavor.objects.filter(external_id=p['id']).first() if not flavor: flavor = Flavor.objects.filter(name=title, is_legacy=False).first() - if flavor: - flavor.external_id = p['id'] - flavor.name = title - flavor.category = category - flavor.description = description - flavor.shop_url = shop_url - flavor.is_available = is_available - flavor.is_legacy = False # API flavors are not legacy - - # Cache image if URL changed or local image missing - if image_url and (flavor.image_url != image_url or not flavor.image): - img_file = self.download_image(image_url, title) - if img_file: - flavor.image.save(img_file.name, img_file, save=False) - - flavor.image_url = image_url - flavor.save() - updated_count += 1 - else: - new_flavor = Flavor( - external_id=p['id'], - name=title, - category=category, - description=description, - image_url=image_url, - shop_url=shop_url, - is_available=is_available, - is_legacy=False - ) - if image_url: - img_file = self.download_image(image_url, title) - if img_file: - new_flavor.image.save(img_file.name, img_file, save=False) - new_flavor.save() + if not flavor: + flavor = Flavor(external_id=p['id'], name=title, is_legacy=False) created_count += 1 + else: + updated_count += 1 + + flavor.category = category + flavor.description = description + flavor.shop_url = shop_url + flavor.is_available = is_available + flavor.external_id = p['id'] # Ensure ID is set + if image_url: + # Check if local file exists + file_exists = False + if flavor.image: + abs_path = os.path.join(settings.MEDIA_ROOT, flavor.image.name) + if os.path.exists(abs_path): + file_exists = True + + # Download if missing or URL changed + if not file_exists or flavor.image_url != image_url: + rel_path = self.download_image(image_url, title) + if rel_path: + flavor.image = rel_path + self.stdout.write(f"Downloaded image for: {title}") + else: + self.stdout.write(self.style.WARNING(f"Failed to ensure image for: {title}")) + + flavor.image_url = image_url + flavor.save() synced_external_ids.append(p['id']) - # Mark flavors NOT in the sync as unavailable (only for those that have an external_id) - # These are discontinued API flavors. discontinued_count = Flavor.objects.filter(external_id__isnull=False).exclude(external_id__in=synced_external_ids).update(is_available=False) - self.stdout.write(self.style.SUCCESS(f"Finished! Created: {created_count}, Updated: {updated_count}, Marked Unavailable: {discontinued_count}")) diff --git a/backend/media/flavors/3er-box-energy-cherry-cheetah.png b/backend/media/flavors/3er-box-energy-cherry-cheetah.png new file mode 100644 index 0000000..46d71a0 Binary files /dev/null and b/backend/media/flavors/3er-box-energy-cherry-cheetah.png differ diff --git a/backend/media/flavors/acai-anaconda.jpg b/backend/media/flavors/acai-anaconda.jpg new file mode 100644 index 0000000..d45273d Binary files /dev/null and b/backend/media/flavors/acai-anaconda.jpg differ diff --git a/backend/media/flavors/acai.jpg b/backend/media/flavors/acai.jpg new file mode 100644 index 0000000..5d95956 Binary files /dev/null and b/backend/media/flavors/acai.jpg differ diff --git a/backend/media/flavors/ananas.png b/backend/media/flavors/ananas.png new file mode 100644 index 0000000..0723a7a Binary files /dev/null and b/backend/media/flavors/ananas.png differ diff --git a/backend/media/flavors/apfel.jpg b/backend/media/flavors/apfel.jpg new file mode 100644 index 0000000..40ce5bf Binary files /dev/null and b/backend/media/flavors/apfel.jpg differ diff --git a/backend/media/flavors/apple-alligator.jpg b/backend/media/flavors/apple-alligator.jpg new file mode 100644 index 0000000..7378e70 Binary files /dev/null and b/backend/media/flavors/apple-alligator.jpg differ diff --git a/backend/media/flavors/badeschlappen.png b/backend/media/flavors/badeschlappen.png new file mode 100644 index 0000000..a962eb2 Binary files /dev/null and b/backend/media/flavors/badeschlappen.png differ diff --git a/backend/media/flavors/banane.jpg b/backend/media/flavors/banane.jpg new file mode 100644 index 0000000..4e81c47 Binary files /dev/null and b/backend/media/flavors/banane.jpg differ diff --git a/backend/media/flavors/birne.jpg b/backend/media/flavors/birne.jpg new file mode 100644 index 0000000..05feb8d Binary files /dev/null and b/backend/media/flavors/birne.jpg differ diff --git a/backend/media/flavors/blood-orange-bat.jpg b/backend/media/flavors/blood-orange-bat.jpg new file mode 100644 index 0000000..6fc5c44 Binary files /dev/null and b/backend/media/flavors/blood-orange-bat.jpg differ diff --git a/backend/media/flavors/blueberry-bear.jpg b/backend/media/flavors/blueberry-bear.jpg new file mode 100644 index 0000000..6babf34 Binary files /dev/null and b/backend/media/flavors/blueberry-bear.jpg differ diff --git a/backend/media/flavors/bratapfel.jpg b/backend/media/flavors/bratapfel.jpg new file mode 100644 index 0000000..1c25551 Binary files /dev/null and b/backend/media/flavors/bratapfel.jpg differ diff --git a/backend/media/flavors/brombeere.png b/backend/media/flavors/brombeere.png new file mode 100644 index 0000000..81cd3c3 Binary files /dev/null and b/backend/media/flavors/brombeere.png differ diff --git a/backend/media/flavors/bubblegum-butterfly.jpg b/backend/media/flavors/bubblegum-butterfly.jpg new file mode 100644 index 0000000..33adcdd Binary files /dev/null and b/backend/media/flavors/bubblegum-butterfly.jpg differ diff --git a/backend/media/flavors/burrsday-shaker.png b/backend/media/flavors/burrsday-shaker.png new file mode 100644 index 0000000..95a3141 Binary files /dev/null and b/backend/media/flavors/burrsday-shaker.png differ diff --git a/backend/media/flavors/cactus-camel.jpg b/backend/media/flavors/cactus-camel.jpg new file mode 100644 index 0000000..81ecb3e Binary files /dev/null and b/backend/media/flavors/cactus-camel.jpg differ diff --git a/backend/media/flavors/cherry-cheetah.jpg b/backend/media/flavors/cherry-cheetah.jpg new file mode 100644 index 0000000..e307128 Binary files /dev/null and b/backend/media/flavors/cherry-cheetah.jpg differ diff --git a/backend/media/flavors/citrus-cobra.jpg b/backend/media/flavors/citrus-cobra.jpg new file mode 100644 index 0000000..a806999 Binary files /dev/null and b/backend/media/flavors/citrus-cobra.jpg differ diff --git a/backend/media/flavors/community-thermo-shaker.jpg b/backend/media/flavors/community-thermo-shaker.jpg new file mode 100644 index 0000000..42a1781 Binary files /dev/null and b/backend/media/flavors/community-thermo-shaker.jpg differ diff --git a/backend/media/flavors/cranberry.jpg b/backend/media/flavors/cranberry.jpg new file mode 100644 index 0000000..caea8f9 Binary files /dev/null and b/backend/media/flavors/cranberry.jpg differ diff --git a/backend/media/flavors/darjeeling-x-honig.jpg b/backend/media/flavors/darjeeling-x-honig.jpg new file mode 100644 index 0000000..c5ab399 Binary files /dev/null and b/backend/media/flavors/darjeeling-x-honig.jpg differ diff --git a/backend/media/flavors/dosierloffel-metall.png b/backend/media/flavors/dosierloffel-metall.png new file mode 100644 index 0000000..93f0e7c Binary files /dev/null and b/backend/media/flavors/dosierloffel-metall.png differ diff --git a/backend/media/flavors/drachenfrucht.jpg b/backend/media/flavors/drachenfrucht.jpg new file mode 100644 index 0000000..52353c0 Binary files /dev/null and b/backend/media/flavors/drachenfrucht.jpg differ diff --git a/backend/media/flavors/dragon-fruit-dragon.jpg b/backend/media/flavors/dragon-fruit-dragon.jpg new file mode 100644 index 0000000..bdf73f3 Binary files /dev/null and b/backend/media/flavors/dragon-fruit-dragon.jpg differ diff --git a/backend/media/flavors/einzelsorten-box-energy.jpg b/backend/media/flavors/einzelsorten-box-energy.jpg new file mode 100644 index 0000000..671a5bb Binary files /dev/null and b/backend/media/flavors/einzelsorten-box-energy.jpg differ diff --git a/backend/media/flavors/einzelsorten-box-hydration.jpg b/backend/media/flavors/einzelsorten-box-hydration.jpg new file mode 100644 index 0000000..d55703e Binary files /dev/null and b/backend/media/flavors/einzelsorten-box-hydration.jpg differ diff --git a/backend/media/flavors/einzelsorten-box-iced-tea.webp b/backend/media/flavors/einzelsorten-box-iced-tea.webp new file mode 100644 index 0000000..17bbee2 Binary files /dev/null and b/backend/media/flavors/einzelsorten-box-iced-tea.webp differ diff --git a/backend/media/flavors/einzelsorten-box-milkshake.jpg b/backend/media/flavors/einzelsorten-box-milkshake.jpg new file mode 100644 index 0000000..bd8208d Binary files /dev/null and b/backend/media/flavors/einzelsorten-box-milkshake.jpg differ diff --git a/backend/media/flavors/energy-probe.png b/backend/media/flavors/energy-probe.png new file mode 100644 index 0000000..49778d5 Binary files /dev/null and b/backend/media/flavors/energy-probe.png differ diff --git a/backend/media/flavors/energy-starter-set.jpg b/backend/media/flavors/energy-starter-set.jpg new file mode 100644 index 0000000..25a885a Binary files /dev/null and b/backend/media/flavors/energy-starter-set.jpg differ diff --git a/backend/media/flavors/erdbeere-x-kiwi.jpg b/backend/media/flavors/erdbeere-x-kiwi.jpg new file mode 100644 index 0000000..a35a8a2 Binary files /dev/null and b/backend/media/flavors/erdbeere-x-kiwi.jpg differ diff --git a/backend/media/flavors/erdbeere.jpg b/backend/media/flavors/erdbeere.jpg new file mode 100644 index 0000000..b3e36fd Binary files /dev/null and b/backend/media/flavors/erdbeere.jpg differ diff --git a/backend/media/flavors/erdbeere.webp b/backend/media/flavors/erdbeere.webp new file mode 100644 index 0000000..085d885 Binary files /dev/null and b/backend/media/flavors/erdbeere.webp differ diff --git a/backend/media/flavors/ersatzdichtung-glasflasche.png b/backend/media/flavors/ersatzdichtung-glasflasche.png new file mode 100644 index 0000000..0fea288 Binary files /dev/null and b/backend/media/flavors/ersatzdichtung-glasflasche.png differ diff --git a/backend/media/flavors/ersatzteil-shaker.png b/backend/media/flavors/ersatzteil-shaker.png new file mode 100644 index 0000000..a4b78c3 Binary files /dev/null and b/backend/media/flavors/ersatzteil-shaker.png differ diff --git a/backend/media/flavors/ersatzteile-thermo-shaker-1l.webp b/backend/media/flavors/ersatzteile-thermo-shaker-1l.webp new file mode 100644 index 0000000..77c7aec Binary files /dev/null and b/backend/media/flavors/ersatzteile-thermo-shaker-1l.webp differ diff --git a/backend/media/flavors/ersatzteile-thermo-shaker.png b/backend/media/flavors/ersatzteile-thermo-shaker.png new file mode 100644 index 0000000..5477849 Binary files /dev/null and b/backend/media/flavors/ersatzteile-thermo-shaker.png differ diff --git a/backend/media/flavors/ersatzteile-thermo-shaker.webp b/backend/media/flavors/ersatzteile-thermo-shaker.webp new file mode 100644 index 0000000..77c7aec Binary files /dev/null and b/backend/media/flavors/ersatzteile-thermo-shaker.webp differ diff --git a/backend/media/flavors/fanschal-1-fc-koln.webp b/backend/media/flavors/fanschal-1-fc-koln.webp new file mode 100644 index 0000000..8f96328 Binary files /dev/null and b/backend/media/flavors/fanschal-1-fc-koln.webp differ diff --git a/backend/media/flavors/frosty-fox.jpg b/backend/media/flavors/frosty-fox.jpg new file mode 100644 index 0000000..afb5d50 Binary files /dev/null and b/backend/media/flavors/frosty-fox.jpg differ diff --git a/backend/media/flavors/fruity-frog.png b/backend/media/flavors/fruity-frog.png new file mode 100644 index 0000000..8c75be8 Binary files /dev/null and b/backend/media/flavors/fruity-frog.png differ diff --git a/backend/media/flavors/geschenkgutschein.png b/backend/media/flavors/geschenkgutschein.png new file mode 100644 index 0000000..d3d120a Binary files /dev/null and b/backend/media/flavors/geschenkgutschein.png differ diff --git a/backend/media/flavors/giga-gallon-wei.png b/backend/media/flavors/giga-gallon-wei.png new file mode 100644 index 0000000..8f0e217 Binary files /dev/null and b/backend/media/flavors/giga-gallon-wei.png differ diff --git a/backend/media/flavors/gorillas-grape.jpg b/backend/media/flavors/gorillas-grape.jpg new file mode 100644 index 0000000..fcf1049 Binary files /dev/null and b/backend/media/flavors/gorillas-grape.jpg differ diff --git a/backend/media/flavors/grapefruit-giraffe.jpg b/backend/media/flavors/grapefruit-giraffe.jpg new file mode 100644 index 0000000..c90e924 Binary files /dev/null and b/backend/media/flavors/grapefruit-giraffe.jpg differ diff --git a/backend/media/flavors/grapefruit.jpg b/backend/media/flavors/grapefruit.jpg new file mode 100644 index 0000000..e197829 Binary files /dev/null and b/backend/media/flavors/grapefruit.jpg differ diff --git a/backend/media/flavors/gruner-tee.png b/backend/media/flavors/gruner-tee.png new file mode 100644 index 0000000..c732f7a Binary files /dev/null and b/backend/media/flavors/gruner-tee.png differ diff --git a/backend/media/flavors/guave.jpg b/backend/media/flavors/guave.jpg new file mode 100644 index 0000000..213d118 Binary files /dev/null and b/backend/media/flavors/guave.jpg differ diff --git a/backend/media/flavors/haselnuss.jpg b/backend/media/flavors/haselnuss.jpg new file mode 100644 index 0000000..88d1980 Binary files /dev/null and b/backend/media/flavors/haselnuss.jpg differ diff --git a/backend/media/flavors/hibiskus.png b/backend/media/flavors/hibiskus.png new file mode 100644 index 0000000..c2c1419 Binary files /dev/null and b/backend/media/flavors/hibiskus.png differ diff --git a/backend/media/flavors/himbeere-x-vanille.jpg b/backend/media/flavors/himbeere-x-vanille.jpg new file mode 100644 index 0000000..099d106 Binary files /dev/null and b/backend/media/flavors/himbeere-x-vanille.jpg differ diff --git a/backend/media/flavors/holy-brushed-logo-thermo-shaker-adventcalendar.png b/backend/media/flavors/holy-brushed-logo-thermo-shaker-adventcalendar.png new file mode 100644 index 0000000..bb3856e Binary files /dev/null and b/backend/media/flavors/holy-brushed-logo-thermo-shaker-adventcalendar.png differ diff --git a/backend/media/flavors/holy-geschenkbox.png b/backend/media/flavors/holy-geschenkbox.png new file mode 100644 index 0000000..2261efe Binary files /dev/null and b/backend/media/flavors/holy-geschenkbox.png differ diff --git a/backend/media/flavors/holy-holy-holy-shaker.png b/backend/media/flavors/holy-holy-holy-shaker.png new file mode 100644 index 0000000..5da30fe Binary files /dev/null and b/backend/media/flavors/holy-holy-holy-shaker.png differ diff --git a/backend/media/flavors/holy-lowen-frankfurt-shaker.png b/backend/media/flavors/holy-lowen-frankfurt-shaker.png new file mode 100644 index 0000000..47fea1f Binary files /dev/null and b/backend/media/flavors/holy-lowen-frankfurt-shaker.png differ diff --git a/backend/media/flavors/holy-pflege-shaker.png b/backend/media/flavors/holy-pflege-shaker.png new file mode 100644 index 0000000..6668fa8 Binary files /dev/null and b/backend/media/flavors/holy-pflege-shaker.png differ diff --git a/backend/media/flavors/holy-squad-shaker.jpg b/backend/media/flavors/holy-squad-shaker.jpg new file mode 100644 index 0000000..cd78e6b Binary files /dev/null and b/backend/media/flavors/holy-squad-shaker.jpg differ diff --git a/backend/media/flavors/holy-x-7-vs-wild-thermo-shaker-2025.png b/backend/media/flavors/holy-x-7-vs-wild-thermo-shaker-2025.png new file mode 100644 index 0000000..b9457bf Binary files /dev/null and b/backend/media/flavors/holy-x-7-vs-wild-thermo-shaker-2025.png differ diff --git a/backend/media/flavors/holy-x-mission-unknown-shaker.png b/backend/media/flavors/holy-x-mission-unknown-shaker.png new file mode 100644 index 0000000..37d205f Binary files /dev/null and b/backend/media/flavors/holy-x-mission-unknown-shaker.png differ diff --git a/backend/media/flavors/honigmelone.jpg b/backend/media/flavors/honigmelone.jpg new file mode 100644 index 0000000..da8fb61 Binary files /dev/null and b/backend/media/flavors/honigmelone.jpg differ diff --git a/backend/media/flavors/hotfoot-run-turnbeutel.png b/backend/media/flavors/hotfoot-run-turnbeutel.png new file mode 100644 index 0000000..77edda0 Binary files /dev/null and b/backend/media/flavors/hotfoot-run-turnbeutel.png differ diff --git a/backend/media/flavors/hydration-probe.png b/backend/media/flavors/hydration-probe.png new file mode 100644 index 0000000..7c59cf0 Binary files /dev/null and b/backend/media/flavors/hydration-probe.png differ diff --git a/backend/media/flavors/hydration-starter-set.jpg b/backend/media/flavors/hydration-starter-set.jpg new file mode 100644 index 0000000..898153e Binary files /dev/null and b/backend/media/flavors/hydration-starter-set.jpg differ diff --git a/backend/media/flavors/iced-tea-probe.webp b/backend/media/flavors/iced-tea-probe.webp new file mode 100644 index 0000000..e100b39 Binary files /dev/null and b/backend/media/flavors/iced-tea-probe.webp differ diff --git a/backend/media/flavors/iced-tea-starter-set.jpg b/backend/media/flavors/iced-tea-starter-set.jpg new file mode 100644 index 0000000..820f7c4 Binary files /dev/null and b/backend/media/flavors/iced-tea-starter-set.jpg differ diff --git a/backend/media/flavors/kappe-hotfoot-run.png b/backend/media/flavors/kappe-hotfoot-run.png new file mode 100644 index 0000000..06a1db3 Binary files /dev/null and b/backend/media/flavors/kappe-hotfoot-run.png differ diff --git a/backend/media/flavors/karamell.jpg b/backend/media/flavors/karamell.jpg new file mode 100644 index 0000000..1a4af65 Binary files /dev/null and b/backend/media/flavors/karamell.jpg differ diff --git a/backend/media/flavors/kiwi-komodo.jpg b/backend/media/flavors/kiwi-komodo.jpg new file mode 100644 index 0000000..6f2a19f Binary files /dev/null and b/backend/media/flavors/kiwi-komodo.jpg differ diff --git a/backend/media/flavors/kokosnuss.png b/backend/media/flavors/kokosnuss.png new file mode 100644 index 0000000..6facb00 Binary files /dev/null and b/backend/media/flavors/kokosnuss.png differ diff --git a/backend/media/flavors/kolle-kamelle.webp b/backend/media/flavors/kolle-kamelle.webp new file mode 100644 index 0000000..fb83f7e Binary files /dev/null and b/backend/media/flavors/kolle-kamelle.webp differ diff --git a/backend/media/flavors/kuhltasche.png b/backend/media/flavors/kuhltasche.png new file mode 100644 index 0000000..1cd428d Binary files /dev/null and b/backend/media/flavors/kuhltasche.png differ diff --git a/backend/media/flavors/legacy_dolphin-daiquiri.png b/backend/media/flavors/legacy_dolphin-daiquiri.png new file mode 100644 index 0000000..9adcf21 Binary files /dev/null and b/backend/media/flavors/legacy_dolphin-daiquiri.png differ diff --git a/backend/media/flavors/legacy_hitschies-saure-drachenzunge-blau.png b/backend/media/flavors/legacy_hitschies-saure-drachenzunge-blau.png new file mode 100644 index 0000000..83176ae Binary files /dev/null and b/backend/media/flavors/legacy_hitschies-saure-drachenzunge-blau.png differ diff --git a/backend/media/flavors/legacy_hitschies-saure-krakenarme.png b/backend/media/flavors/legacy_hitschies-saure-krakenarme.png new file mode 100644 index 0000000..d71a1d8 Binary files /dev/null and b/backend/media/flavors/legacy_hitschies-saure-krakenarme.png differ diff --git a/backend/media/flavors/legacy_hitschies-saure-spinnenbeine.png b/backend/media/flavors/legacy_hitschies-saure-spinnenbeine.png new file mode 100644 index 0000000..336929c Binary files /dev/null and b/backend/media/flavors/legacy_hitschies-saure-spinnenbeine.png differ diff --git a/backend/media/flavors/lemon-lizard.jpg b/backend/media/flavors/lemon-lizard.jpg new file mode 100644 index 0000000..f6993d8 Binary files /dev/null and b/backend/media/flavors/lemon-lizard.jpg differ diff --git a/backend/media/flavors/limette-x-matcha-x-minze.jpg b/backend/media/flavors/limette-x-matcha-x-minze.jpg new file mode 100644 index 0000000..8f24ab6 Binary files /dev/null and b/backend/media/flavors/limette-x-matcha-x-minze.jpg differ diff --git a/backend/media/flavors/limited-strawberry-shark.png b/backend/media/flavors/limited-strawberry-shark.png new file mode 100644 index 0000000..cfea85c Binary files /dev/null and b/backend/media/flavors/limited-strawberry-shark.png differ diff --git a/backend/media/flavors/lions-lemonade.jpg b/backend/media/flavors/lions-lemonade.jpg new file mode 100644 index 0000000..2c5f232 Binary files /dev/null and b/backend/media/flavors/lions-lemonade.jpg differ diff --git a/backend/media/flavors/logo-shaker.png b/backend/media/flavors/logo-shaker.png new file mode 100644 index 0000000..6f8964f Binary files /dev/null and b/backend/media/flavors/logo-shaker.png differ diff --git a/backend/media/flavors/lollipop-lovebird.webp b/backend/media/flavors/lollipop-lovebird.webp new file mode 100644 index 0000000..e8ed170 Binary files /dev/null and b/backend/media/flavors/lollipop-lovebird.webp differ diff --git a/backend/media/flavors/mango-x-passionsfrucht.png b/backend/media/flavors/mango-x-passionsfrucht.png new file mode 100644 index 0000000..9c2e418 Binary files /dev/null and b/backend/media/flavors/mango-x-passionsfrucht.png differ diff --git a/backend/media/flavors/milkshake-probe.png b/backend/media/flavors/milkshake-probe.png new file mode 100644 index 0000000..aa4ac5e Binary files /dev/null and b/backend/media/flavors/milkshake-probe.png differ diff --git a/backend/media/flavors/milkshake-starter-set.png b/backend/media/flavors/milkshake-starter-set.png new file mode 100644 index 0000000..0681110 Binary files /dev/null and b/backend/media/flavors/milkshake-starter-set.png differ diff --git a/backend/media/flavors/mix-probier-box-energy.png b/backend/media/flavors/mix-probier-box-energy.png new file mode 100644 index 0000000..0f0fa7f Binary files /dev/null and b/backend/media/flavors/mix-probier-box-energy.png differ diff --git a/backend/media/flavors/mix-probier-box-hydration.png b/backend/media/flavors/mix-probier-box-hydration.png new file mode 100644 index 0000000..755cfb8 Binary files /dev/null and b/backend/media/flavors/mix-probier-box-hydration.png differ diff --git a/backend/media/flavors/mix-probier-box-iced-tea-classics.webp b/backend/media/flavors/mix-probier-box-iced-tea-classics.webp new file mode 100644 index 0000000..608a48b Binary files /dev/null and b/backend/media/flavors/mix-probier-box-iced-tea-classics.webp differ diff --git a/backend/media/flavors/mix-probier-box-iced-tea.png b/backend/media/flavors/mix-probier-box-iced-tea.png new file mode 100644 index 0000000..31e31c2 Binary files /dev/null and b/backend/media/flavors/mix-probier-box-iced-tea.png differ diff --git a/backend/media/flavors/mix-probier-box-milkshake.png b/backend/media/flavors/mix-probier-box-milkshake.png new file mode 100644 index 0000000..f4dc887 Binary files /dev/null and b/backend/media/flavors/mix-probier-box-milkshake.png differ diff --git a/backend/media/flavors/multivitamin.jpg b/backend/media/flavors/multivitamin.jpg new file mode 100644 index 0000000..941cc2d Binary files /dev/null and b/backend/media/flavors/multivitamin.jpg differ diff --git a/backend/media/flavors/orange.jpg b/backend/media/flavors/orange.jpg new file mode 100644 index 0000000..2abf847 Binary files /dev/null and b/backend/media/flavors/orange.jpg differ diff --git a/backend/media/flavors/passionsfrucht.jpg b/backend/media/flavors/passionsfrucht.jpg new file mode 100644 index 0000000..f24c980 Binary files /dev/null and b/backend/media/flavors/passionsfrucht.jpg differ diff --git a/backend/media/flavors/peach-panther.jpg b/backend/media/flavors/peach-panther.jpg new file mode 100644 index 0000000..ce445bd Binary files /dev/null and b/backend/media/flavors/peach-panther.jpg differ diff --git a/backend/media/flavors/peacocks-punch.jpg b/backend/media/flavors/peacocks-punch.jpg new file mode 100644 index 0000000..6822c43 Binary files /dev/null and b/backend/media/flavors/peacocks-punch.jpg differ diff --git a/backend/media/flavors/pfirsich.jpg b/backend/media/flavors/pfirsich.jpg new file mode 100644 index 0000000..a0c21d1 Binary files /dev/null and b/backend/media/flavors/pfirsich.jpg differ diff --git a/backend/media/flavors/pomegranate-piranha.jpg b/backend/media/flavors/pomegranate-piranha.jpg new file mode 100644 index 0000000..2f08cf7 Binary files /dev/null and b/backend/media/flavors/pomegranate-piranha.jpg differ diff --git a/backend/media/flavors/premium-hoodie-blackweek.png b/backend/media/flavors/premium-hoodie-blackweek.png new file mode 100644 index 0000000..b839239 Binary files /dev/null and b/backend/media/flavors/premium-hoodie-blackweek.png differ diff --git a/backend/media/flavors/raspberry-raptor.jpg b/backend/media/flavors/raspberry-raptor.jpg new file mode 100644 index 0000000..4a31f5f Binary files /dev/null and b/backend/media/flavors/raspberry-raptor.jpg differ diff --git a/backend/media/flavors/rote-traube.jpg b/backend/media/flavors/rote-traube.jpg new file mode 100644 index 0000000..934a1c4 Binary files /dev/null and b/backend/media/flavors/rote-traube.jpg differ diff --git a/backend/media/flavors/sauerkirsche.png b/backend/media/flavors/sauerkirsche.png new file mode 100644 index 0000000..9b028e6 Binary files /dev/null and b/backend/media/flavors/sauerkirsche.png differ diff --git a/backend/media/flavors/schwarzer-tee.png b/backend/media/flavors/schwarzer-tee.png new file mode 100644 index 0000000..744960b Binary files /dev/null and b/backend/media/flavors/schwarzer-tee.png differ diff --git a/backend/media/flavors/shaker-1-fc-koln.webp b/backend/media/flavors/shaker-1-fc-koln.webp new file mode 100644 index 0000000..bea18d7 Binary files /dev/null and b/backend/media/flavors/shaker-1-fc-koln.webp differ diff --git a/backend/media/flavors/shaker-energy.webp b/backend/media/flavors/shaker-energy.webp new file mode 100644 index 0000000..a7e2254 Binary files /dev/null and b/backend/media/flavors/shaker-energy.webp differ diff --git a/backend/media/flavors/shaker-hydration.jpg b/backend/media/flavors/shaker-hydration.jpg new file mode 100644 index 0000000..e197829 Binary files /dev/null and b/backend/media/flavors/shaker-hydration.jpg differ diff --git a/backend/media/flavors/shaker-iced-tea.jpg b/backend/media/flavors/shaker-iced-tea.jpg new file mode 100644 index 0000000..e8dcec4 Binary files /dev/null and b/backend/media/flavors/shaker-iced-tea.jpg differ diff --git a/backend/media/flavors/shaker-milkshake.jpg b/backend/media/flavors/shaker-milkshake.jpg new file mode 100644 index 0000000..ed6630c Binary files /dev/null and b/backend/media/flavors/shaker-milkshake.jpg differ diff --git a/backend/media/flavors/spekulatius.jpg b/backend/media/flavors/spekulatius.jpg new file mode 100644 index 0000000..81f1e71 Binary files /dev/null and b/backend/media/flavors/spekulatius.jpg differ diff --git a/backend/media/flavors/spongebob-friends-shaker.png b/backend/media/flavors/spongebob-friends-shaker.png new file mode 100644 index 0000000..8228064 Binary files /dev/null and b/backend/media/flavors/spongebob-friends-shaker.png differ diff --git a/backend/media/flavors/squad-shaker-xl.png b/backend/media/flavors/squad-shaker-xl.png new file mode 100644 index 0000000..7330189 Binary files /dev/null and b/backend/media/flavors/squad-shaker-xl.png differ diff --git a/backend/media/flavors/starter-set-deluxe-lowen-frankfurt.jpg b/backend/media/flavors/starter-set-deluxe-lowen-frankfurt.jpg new file mode 100644 index 0000000..e4646aa Binary files /dev/null and b/backend/media/flavors/starter-set-deluxe-lowen-frankfurt.jpg differ diff --git a/backend/media/flavors/starter-set-deluxe-thermo-shaker.png b/backend/media/flavors/starter-set-deluxe-thermo-shaker.png new file mode 100644 index 0000000..01408d8 Binary files /dev/null and b/backend/media/flavors/starter-set-deluxe-thermo-shaker.png differ diff --git a/backend/media/flavors/starter-set-deluxe.jpg b/backend/media/flavors/starter-set-deluxe.jpg new file mode 100644 index 0000000..d3e1fe5 Binary files /dev/null and b/backend/media/flavors/starter-set-deluxe.jpg differ diff --git a/backend/media/flavors/starter-set-deluxe.png b/backend/media/flavors/starter-set-deluxe.png new file mode 100644 index 0000000..11ae4db Binary files /dev/null and b/backend/media/flavors/starter-set-deluxe.png differ diff --git a/backend/media/flavors/stell-dir-dein-starter-set-zusammen.jpg b/backend/media/flavors/stell-dir-dein-starter-set-zusammen.jpg new file mode 100644 index 0000000..2084b0e Binary files /dev/null and b/backend/media/flavors/stell-dir-dein-starter-set-zusammen.jpg differ diff --git a/backend/media/flavors/strawberry-shark.jpg b/backend/media/flavors/strawberry-shark.jpg new file mode 100644 index 0000000..fb066bf Binary files /dev/null and b/backend/media/flavors/strawberry-shark.jpg differ diff --git a/backend/media/flavors/tangerine-tarantula.png b/backend/media/flavors/tangerine-tarantula.png new file mode 100644 index 0000000..449444a Binary files /dev/null and b/backend/media/flavors/tangerine-tarantula.png differ diff --git a/backend/media/flavors/thai-lime-toucan.jpg b/backend/media/flavors/thai-lime-toucan.jpg new file mode 100644 index 0000000..4a84948 Binary files /dev/null and b/backend/media/flavors/thai-lime-toucan.jpg differ diff --git a/backend/media/flavors/thermo-shaker-1-fc-koln.webp b/backend/media/flavors/thermo-shaker-1-fc-koln.webp new file mode 100644 index 0000000..d94394b Binary files /dev/null and b/backend/media/flavors/thermo-shaker-1-fc-koln.webp differ diff --git a/backend/media/flavors/thermo-shaker-1l-blau.png b/backend/media/flavors/thermo-shaker-1l-blau.png new file mode 100644 index 0000000..dcca6fe Binary files /dev/null and b/backend/media/flavors/thermo-shaker-1l-blau.png differ diff --git a/backend/media/flavors/thermo-shaker-1l-new-year.png b/backend/media/flavors/thermo-shaker-1l-new-year.png new file mode 100644 index 0000000..d47cdf2 Binary files /dev/null and b/backend/media/flavors/thermo-shaker-1l-new-year.png differ diff --git a/backend/media/flavors/thermo-shaker-1l.webp b/backend/media/flavors/thermo-shaker-1l.webp new file mode 100644 index 0000000..8c665e0 Binary files /dev/null and b/backend/media/flavors/thermo-shaker-1l.webp differ diff --git a/backend/media/flavors/thermo-shaker-700ml-new-year-mit-sport-deckel.png b/backend/media/flavors/thermo-shaker-700ml-new-year-mit-sport-deckel.png new file mode 100644 index 0000000..f666f90 Binary files /dev/null and b/backend/media/flavors/thermo-shaker-700ml-new-year-mit-sport-deckel.png differ diff --git a/backend/media/flavors/thermo-shaker-700ml-new-year.png b/backend/media/flavors/thermo-shaker-700ml-new-year.png new file mode 100644 index 0000000..0d6ae41 Binary files /dev/null and b/backend/media/flavors/thermo-shaker-700ml-new-year.png differ diff --git a/backend/media/flavors/thermo-shaker-multichrom.png b/backend/media/flavors/thermo-shaker-multichrom.png new file mode 100644 index 0000000..758bc2a Binary files /dev/null and b/backend/media/flavors/thermo-shaker-multichrom.png differ diff --git a/backend/media/flavors/thermo-shaker-spongebob.jpg b/backend/media/flavors/thermo-shaker-spongebob.jpg new file mode 100644 index 0000000..62aab15 Binary files /dev/null and b/backend/media/flavors/thermo-shaker-spongebob.jpg differ diff --git a/backend/media/flavors/thermo-shaker-sports-lid.jpg b/backend/media/flavors/thermo-shaker-sports-lid.jpg new file mode 100644 index 0000000..ac03d71 Binary files /dev/null and b/backend/media/flavors/thermo-shaker-sports-lid.jpg differ diff --git a/backend/media/flavors/thermo-shaker-sportsfreund.png b/backend/media/flavors/thermo-shaker-sportsfreund.png new file mode 100644 index 0000000..4698365 Binary files /dev/null and b/backend/media/flavors/thermo-shaker-sportsfreund.png differ diff --git a/backend/media/flavors/thermo-shaker.jpg b/backend/media/flavors/thermo-shaker.jpg new file mode 100644 index 0000000..f21ef3f Binary files /dev/null and b/backend/media/flavors/thermo-shaker.jpg differ diff --git a/backend/media/flavors/thermo-shaker.png b/backend/media/flavors/thermo-shaker.png new file mode 100644 index 0000000..5f63da4 Binary files /dev/null and b/backend/media/flavors/thermo-shaker.png differ diff --git a/backend/media/flavors/tropical-tiger.jpg b/backend/media/flavors/tropical-tiger.jpg new file mode 100644 index 0000000..d5b510d Binary files /dev/null and b/backend/media/flavors/tropical-tiger.jpg differ diff --git a/backend/media/flavors/vanille.jpg b/backend/media/flavors/vanille.jpg new file mode 100644 index 0000000..518d73a Binary files /dev/null and b/backend/media/flavors/vanille.jpg differ diff --git a/backend/media/flavors/wassermelone.jpg b/backend/media/flavors/wassermelone.jpg new file mode 100644 index 0000000..f4b7493 Binary files /dev/null and b/backend/media/flavors/wassermelone.jpg differ diff --git a/backend/media/flavors/watermelon-whale.jpg b/backend/media/flavors/watermelon-whale.jpg new file mode 100644 index 0000000..8738004 Binary files /dev/null and b/backend/media/flavors/watermelon-whale.jpg differ diff --git a/backend/media/flavors/weier-pfirsich.jpg b/backend/media/flavors/weier-pfirsich.jpg new file mode 100644 index 0000000..2b260c9 Binary files /dev/null and b/backend/media/flavors/weier-pfirsich.jpg differ diff --git a/backend/media/flavors/wildberry-wolf.jpg b/backend/media/flavors/wildberry-wolf.jpg new file mode 100644 index 0000000..8684ec7 Binary files /dev/null and b/backend/media/flavors/wildberry-wolf.jpg differ diff --git a/backend/media/flavors/winter-punch.jpg b/backend/media/flavors/winter-punch.jpg new file mode 100644 index 0000000..95a6335 Binary files /dev/null and b/backend/media/flavors/winter-punch.jpg differ diff --git a/backend/media/flavors/woodruff-wolf.jpg b/backend/media/flavors/woodruff-wolf.jpg new file mode 100644 index 0000000..8e9e94e Binary files /dev/null and b/backend/media/flavors/woodruff-wolf.jpg differ diff --git a/backend/media/flavors/zitrone-x-honig.jpg b/backend/media/flavors/zitrone-x-honig.jpg new file mode 100644 index 0000000..9ba952c Binary files /dev/null and b/backend/media/flavors/zitrone-x-honig.jpg differ diff --git a/backend/media/flavors/zitrone.jpg b/backend/media/flavors/zitrone.jpg new file mode 100644 index 0000000..0eb1f4f Binary files /dev/null and b/backend/media/flavors/zitrone.jpg differ