diff --git a/chorechef_backend/chorechef_backend/__init__.py b/chorechef_backend/chorechef_backend/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/chorechef_backend/chorechef_backend/asgi.py b/chorechef_backend/chorechef_backend/asgi.py new file mode 100644 index 0000000000000000000000000000000000000000..ac7570ee88adbd92e0158442d97308764cae089e --- /dev/null +++ b/chorechef_backend/chorechef_backend/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for chorechef_backend project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/5.1/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "chorechef_backend.settings") + +application = get_asgi_application() diff --git a/chorechef_backend/chorechef_backend/settings.py b/chorechef_backend/chorechef_backend/settings.py new file mode 100644 index 0000000000000000000000000000000000000000..172ad7e48e43d032f0205e25d11b9563215f8cd4 --- /dev/null +++ b/chorechef_backend/chorechef_backend/settings.py @@ -0,0 +1,132 @@ +""" +Django settings for chorechef_backend project. + +Generated by 'django-admin startproject' using Django 5.1.1. + +For more information on this file, see +https://docs.djangoproject.com/en/5.1/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/5.1/ref/settings/ +""" + +from pathlib import Path + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/5.1/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = "django-insecure-cz#@s%5xbay(6sxd2d*@f_*89)f+%tcwi*g03zuf8+@k@5u=i0" + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = [] + + +# Application definition + +INSTALLED_APPS = [ + "django.contrib.admin", + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.sessions", + "django.contrib.messages", + "django.contrib.staticfiles", + "rest_framework", + "rest", + "corsheaders", +] + +MIDDLEWARE = [ + "django.middleware.security.SecurityMiddleware", + "django.contrib.sessions.middleware.SessionMiddleware", + "django.middleware.common.CommonMiddleware", + "django.middleware.csrf.CsrfViewMiddleware", + "django.contrib.auth.middleware.AuthenticationMiddleware", + "django.contrib.messages.middleware.MessageMiddleware", + "django.middleware.clickjacking.XFrameOptionsMiddleware", + "corsheaders.middleware.CorsMiddleware", + "django.middleware.common.CommonMiddleware", +] + +CORS_ALLOWED_ORIGINS = [ + "http://localhost:5173", +] + +ROOT_URLCONF = "chorechef_backend.urls" + +TEMPLATES = [ + { + "BACKEND": "django.template.backends.django.DjangoTemplates", + "DIRS": [], + "APP_DIRS": True, + "OPTIONS": { + "context_processors": [ + "django.template.context_processors.debug", + "django.template.context_processors.request", + "django.contrib.auth.context_processors.auth", + "django.contrib.messages.context_processors.messages", + ], + }, + }, +] + +WSGI_APPLICATION = "chorechef_backend.wsgi.application" + + +# Database +# https://docs.djangoproject.com/en/5.1/ref/settings/#databases + +DATABASES = { + "default": { + "ENGINE": "django.db.backends.sqlite3", + "NAME": BASE_DIR / "db.sqlite3", + } +} + + +# Password validation +# https://docs.djangoproject.com/en/5.1/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", + }, + { + "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", + }, + { + "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", + }, + { + "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/5.1/topics/i18n/ + +LANGUAGE_CODE = "en-us" + +TIME_ZONE = "UTC" + +USE_I18N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/5.1/howto/static-files/ + +STATIC_URL = "static/" + +# Default primary key field type +# https://docs.djangoproject.com/en/5.1/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" diff --git a/chorechef_backend/chorechef_backend/urls.py b/chorechef_backend/chorechef_backend/urls.py new file mode 100644 index 0000000000000000000000000000000000000000..b88bf7485ebcbd252305a1e6c35b9fa49a54ad35 --- /dev/null +++ b/chorechef_backend/chorechef_backend/urls.py @@ -0,0 +1,24 @@ +""" +URL configuration for chorechef_backend project. + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/5.1/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" + +from django.contrib import admin +from django.urls import include, path + +urlpatterns = [ + path("admin/", admin.site.urls), + path("", include("rest.urls")), +] diff --git a/chorechef_backend/chorechef_backend/wsgi.py b/chorechef_backend/chorechef_backend/wsgi.py new file mode 100644 index 0000000000000000000000000000000000000000..d325044522c43a375838c8f0dd9134dd7d746909 --- /dev/null +++ b/chorechef_backend/chorechef_backend/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for chorechef_backend project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/5.1/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "chorechef_backend.settings") + +application = get_wsgi_application() diff --git a/chorechef_backend/manage.py b/chorechef_backend/manage.py new file mode 100755 index 0000000000000000000000000000000000000000..3b19e5eac627eddec09fefef82815d53cd76cfd1 --- /dev/null +++ b/chorechef_backend/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "chorechef_backend.settings") + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == "__main__": + main() diff --git a/chorechef_backend/requirements.txt b/chorechef_backend/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..e1c394be8578c064e0846f02e4a6e1a81cb880db --- /dev/null +++ b/chorechef_backend/requirements.txt @@ -0,0 +1,4 @@ +django +djangorestframework +pygments +django-cors-headers diff --git a/chorechef_backend/rest/__init__.py b/chorechef_backend/rest/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/chorechef_backend/rest/admin.py b/chorechef_backend/rest/admin.py new file mode 100644 index 0000000000000000000000000000000000000000..2c4a8b64cff5c95708e6c8a8ff1a0ddb4c828b64 --- /dev/null +++ b/chorechef_backend/rest/admin.py @@ -0,0 +1,8 @@ +from django.contrib import admin + +# Register your models here. +from .models import Chore, Meal, User + +admin.site.register(User) +admin.site.register(Chore) +admin.site.register(Meal) diff --git a/chorechef_backend/rest/apps.py b/chorechef_backend/rest/apps.py new file mode 100644 index 0000000000000000000000000000000000000000..576bd5da761fa30b2a4f3f0e20127323e7c63a7c --- /dev/null +++ b/chorechef_backend/rest/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class RestConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "rest" diff --git a/chorechef_backend/rest/migrations/0001_initial.py b/chorechef_backend/rest/migrations/0001_initial.py new file mode 100644 index 0000000000000000000000000000000000000000..f4667fce267d2085805df6c0b2a1d37f69b81b08 --- /dev/null +++ b/chorechef_backend/rest/migrations/0001_initial.py @@ -0,0 +1,20 @@ +# Generated by Django 5.1.1 on 2024-09-12 12:28 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [] + + operations = [ + migrations.CreateModel( + name="User", + fields=[ + ("user_id", models.AutoField(primary_key=True, serialize=False)), + ("username", models.CharField(max_length=50)), + ], + ), + ] diff --git a/chorechef_backend/rest/migrations/0002_chore_meal.py b/chorechef_backend/rest/migrations/0002_chore_meal.py new file mode 100644 index 0000000000000000000000000000000000000000..8b108c7110a6a7c17d4e702d94cbdeaf628fbc09 --- /dev/null +++ b/chorechef_backend/rest/migrations/0002_chore_meal.py @@ -0,0 +1,33 @@ +# Generated by Django 5.1.1 on 2024-09-12 20:54 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("rest", "0001_initial"), + ] + + operations = [ + migrations.CreateModel( + name="Chore", + fields=[ + ("chore_id", models.AutoField(primary_key=True, serialize=False)), + ("chore_name", models.CharField(max_length=50)), + ("chore_date", models.DateField()), + ("chore_frequency", models.IntegerField()), + ("chore_frequency_unit", models.CharField(max_length=50)), + ], + ), + migrations.CreateModel( + name="Meal", + fields=[ + ("meal_id", models.AutoField(primary_key=True, serialize=False)), + ("meal_name", models.CharField(max_length=50)), + ("meal_description", models.CharField(max_length=500)), + ("meal_date", models.DateField()), + ("meal_image", models.ImageField(upload_to="")), + ], + ), + ] diff --git a/chorechef_backend/rest/migrations/0003_alter_meal_meal_image.py b/chorechef_backend/rest/migrations/0003_alter_meal_meal_image.py new file mode 100644 index 0000000000000000000000000000000000000000..ea8828692005049abe2e09fc5ab9ac88511133af --- /dev/null +++ b/chorechef_backend/rest/migrations/0003_alter_meal_meal_image.py @@ -0,0 +1,18 @@ +# Generated by Django 5.1.1 on 2024-09-12 20:57 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("rest", "0002_chore_meal"), + ] + + operations = [ + migrations.AlterField( + model_name="meal", + name="meal_image", + field=models.ImageField(null=True, upload_to=""), + ), + ] diff --git a/chorechef_backend/rest/migrations/0004_remove_meal_meal_id_alter_meal_meal_date.py b/chorechef_backend/rest/migrations/0004_remove_meal_meal_id_alter_meal_meal_date.py new file mode 100644 index 0000000000000000000000000000000000000000..bd5db8fcd2a92f6d4fcc8f0043f16bf235027354 --- /dev/null +++ b/chorechef_backend/rest/migrations/0004_remove_meal_meal_id_alter_meal_meal_date.py @@ -0,0 +1,22 @@ +# Generated by Django 5.1.1 on 2024-09-13 15:13 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("rest", "0003_alter_meal_meal_image"), + ] + + operations = [ + migrations.RemoveField( + model_name="meal", + name="meal_id", + ), + migrations.AlterField( + model_name="meal", + name="meal_date", + field=models.DateField(primary_key=True, serialize=False), + ), + ] diff --git a/chorechef_backend/rest/migrations/0005_alter_meal_meal_description.py b/chorechef_backend/rest/migrations/0005_alter_meal_meal_description.py new file mode 100644 index 0000000000000000000000000000000000000000..b421fb426220fcd89afe63b2519f572bc07c29ba --- /dev/null +++ b/chorechef_backend/rest/migrations/0005_alter_meal_meal_description.py @@ -0,0 +1,18 @@ +# Generated by Django 5.1.1 on 2024-09-13 15:52 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("rest", "0004_remove_meal_meal_id_alter_meal_meal_date"), + ] + + operations = [ + migrations.AlterField( + model_name="meal", + name="meal_description", + field=models.CharField(max_length=500, null=True), + ), + ] diff --git a/chorechef_backend/rest/migrations/0006_alter_meal_meal_description.py b/chorechef_backend/rest/migrations/0006_alter_meal_meal_description.py new file mode 100644 index 0000000000000000000000000000000000000000..d1520d76688cbab9a443e59d1a5537efca018d9a --- /dev/null +++ b/chorechef_backend/rest/migrations/0006_alter_meal_meal_description.py @@ -0,0 +1,18 @@ +# Generated by Django 5.1.1 on 2024-09-13 15:54 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("rest", "0005_alter_meal_meal_description"), + ] + + operations = [ + migrations.AlterField( + model_name="meal", + name="meal_description", + field=models.CharField(blank=True, max_length=500, null=True), + ), + ] diff --git a/chorechef_backend/rest/migrations/0007_chore_chore_done.py b/chorechef_backend/rest/migrations/0007_chore_chore_done.py new file mode 100644 index 0000000000000000000000000000000000000000..a154ae52d56e4d8e32f8931713808d7f7f669d55 --- /dev/null +++ b/chorechef_backend/rest/migrations/0007_chore_chore_done.py @@ -0,0 +1,18 @@ +# Generated by Django 5.1.1 on 2024-09-14 15:55 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("rest", "0006_alter_meal_meal_description"), + ] + + operations = [ + migrations.AddField( + model_name="chore", + name="chore_done", + field=models.BooleanField(default=False), + ), + ] diff --git a/chorechef_backend/rest/migrations/0008_chore_chore_user.py b/chorechef_backend/rest/migrations/0008_chore_chore_user.py new file mode 100644 index 0000000000000000000000000000000000000000..466b90bf9a45d9ed31f88bd82343840dc61153e8 --- /dev/null +++ b/chorechef_backend/rest/migrations/0008_chore_chore_user.py @@ -0,0 +1,24 @@ +# Generated by Django 5.1.1 on 2024-09-15 17:02 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("rest", "0007_chore_chore_done"), + ] + + operations = [ + migrations.AddField( + model_name="chore", + name="chore_user", + field=models.ForeignKey( + default=10, + on_delete=django.db.models.deletion.CASCADE, + to="rest.user", + ), + preserve_default=False, + ), + ] diff --git a/chorechef_backend/rest/migrations/0009_remove_meal_meal_image.py b/chorechef_backend/rest/migrations/0009_remove_meal_meal_image.py new file mode 100644 index 0000000000000000000000000000000000000000..7a91beab6c69345989d2bb0ddf63cbe8ed47d4ef --- /dev/null +++ b/chorechef_backend/rest/migrations/0009_remove_meal_meal_image.py @@ -0,0 +1,17 @@ +# Generated by Django 5.1.1 on 2024-09-18 16:25 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("rest", "0008_chore_chore_user"), + ] + + operations = [ + migrations.RemoveField( + model_name="meal", + name="meal_image", + ), + ] diff --git a/chorechef_backend/rest/migrations/__init__.py b/chorechef_backend/rest/migrations/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/chorechef_backend/rest/models.py b/chorechef_backend/rest/models.py new file mode 100644 index 0000000000000000000000000000000000000000..c709fac9175ab816da4c2707d78357bc73df48fb --- /dev/null +++ b/chorechef_backend/rest/models.py @@ -0,0 +1,24 @@ +from django.db import models + +# Create your models here. + + +class User(models.Model): + user_id = models.AutoField(primary_key=True) + username = models.CharField(max_length=50) + + +class Chore(models.Model): + chore_id = models.AutoField(primary_key=True) + chore_name = models.CharField(max_length=50) + chore_date = models.DateField() + chore_frequency = models.IntegerField() + chore_frequency_unit = models.CharField(max_length=50) + chore_done = models.BooleanField(default=False) + chore_user = models.ForeignKey(User, on_delete=models.CASCADE) + + +class Meal(models.Model): + meal_date = models.DateField(primary_key=True) + meal_name = models.CharField(max_length=50) + meal_description = models.CharField(max_length=500, null=True, blank=True) diff --git a/chorechef_backend/rest/serializers.py b/chorechef_backend/rest/serializers.py new file mode 100644 index 0000000000000000000000000000000000000000..e9f2e06b189e25d80ab768aa20baf25264579f8b --- /dev/null +++ b/chorechef_backend/rest/serializers.py @@ -0,0 +1,21 @@ +from rest_framework import serializers + +from .models import Chore, Meal, User + + +class MealSerializer(serializers.ModelSerializer): + class Meta: + model = Meal + fields = "__all__" + + +class ChoreSerializer(serializers.ModelSerializer): + class Meta: + model = Chore + fields = "__all__" + + +class UserSerializer(serializers.ModelSerializer): + class Meta: + model = User + fields = "__all__" diff --git a/chorechef_backend/rest/tests.py b/chorechef_backend/rest/tests.py new file mode 100644 index 0000000000000000000000000000000000000000..7ce503c2dd97ba78597f6ff6e4393132753573f6 --- /dev/null +++ b/chorechef_backend/rest/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/chorechef_backend/rest/urls.py b/chorechef_backend/rest/urls.py new file mode 100644 index 0000000000000000000000000000000000000000..d43a4b0e28b887c50444178bccef9b2161b0e17c --- /dev/null +++ b/chorechef_backend/rest/urls.py @@ -0,0 +1,12 @@ +from django.urls import path +from rest import views +from rest_framework.urlpatterns import format_suffix_patterns + +urlpatterns = [ + path("meals/", views.MealList.as_view()), + path("meals/<str:pk>/", views.MealDetail.as_view()), + path("chores/", views.ChoreList.as_view()), + path("chores/<str:pk>/", views.ChoreDetail.as_view()), + path("users/", views.UserList.as_view()), + path("users/<str:pk>/", views.UserDetail.as_view()), +] diff --git a/chorechef_backend/rest/views.py b/chorechef_backend/rest/views.py new file mode 100644 index 0000000000000000000000000000000000000000..c5ed87bfbe9aa4c011c214f4d7df43e6155ddeba --- /dev/null +++ b/chorechef_backend/rest/views.py @@ -0,0 +1,36 @@ +from rest_framework import generics + +from .models import Chore, Meal, User +from .serializers import ChoreSerializer, MealSerializer, UserSerializer + +# Create your views here. + + +class MealList(generics.ListCreateAPIView): + queryset = Meal.objects.all() + serializer_class = MealSerializer + + +class MealDetail(generics.RetrieveUpdateDestroyAPIView): + queryset = Meal.objects.all() + serializer_class = MealSerializer + + +class ChoreList(generics.ListCreateAPIView): + queryset = Chore.objects.all() + serializer_class = ChoreSerializer + + +class ChoreDetail(generics.RetrieveUpdateDestroyAPIView): + queryset = Chore.objects.all() + serializer_class = ChoreSerializer + + +class UserList(generics.ListCreateAPIView): + queryset = User.objects.all() + serializer_class = UserSerializer + + +class UserDetail(generics.RetrieveUpdateDestroyAPIView): + queryset = User.objects.all() + serializer_class = UserSerializer diff --git a/chorechef_frontend/env.d.ts b/chorechef_frontend/env.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..11f02fe2a0061d6e6e1f271b21da95423b448b32 --- /dev/null +++ b/chorechef_frontend/env.d.ts @@ -0,0 +1 @@ +/// <reference types="vite/client" /> diff --git a/chorechef_frontend/index.html b/chorechef_frontend/index.html new file mode 100644 index 0000000000000000000000000000000000000000..af787684bb4c94c99b681de3b3dd370aea9c37ce --- /dev/null +++ b/chorechef_frontend/index.html @@ -0,0 +1,21 @@ +<!doctype html> +<html lang="de" class="flex h-full"> + <head> + <meta charset="UTF-8" /> + <link rel="icon" href="/favicon.ico" /> + <link rel="stylesheet" href="https://rsms.me/inter/inter.css" /> + <link rel="preconnect" href="https://fonts.googleapis.com" /> + <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> + <link + href="https://fonts.googleapis.com/css2?family=Indie+Flower&display=swap" + rel="stylesheet" + /> + + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <title>ChoreChef</title> + </head> + <body class="bg-neutral-100 flex flex-col grow"> + <div id="app" class="flex flex-col grow"></div> + <script type="module" src="/src/main.ts"></script> + </body> +</html> diff --git a/chorechef_frontend/package-lock.json b/chorechef_frontend/package-lock.json new file mode 100644 index 0000000000000000000000000000000000000000..4da8c005caa46ef2351a9ecc0db58f4c496dbe2f --- /dev/null +++ b/chorechef_frontend/package-lock.json @@ -0,0 +1,2377 @@ +{ + "name": "chorechef", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "chorechef", + "version": "0.0.0", + "dependencies": { + "@fortawesome/fontawesome-svg-core": "^6.6.0", + "@fortawesome/free-brands-svg-icons": "^6.6.0", + "@fortawesome/free-regular-svg-icons": "^6.6.0", + "@fortawesome/free-solid-svg-icons": "^6.6.0", + "@fortawesome/vue-fontawesome": "^3.0.8", + "@headlessui/vue": "^1.7.23", + "@heroicons/vue": "^2.1.5", + "air-datepicker": "^3.5.3", + "date-fns": "^4.0.0-beta.1", + "moment": "^2.30.1", + "vue": "^3.4.29", + "vue-luxon": "^0.10.0", + "vue-moment": "^4.1.0", + "vue-router": "^4.3.3", + "vue-toastification": "^2.0.0-rc.5" + }, + "devDependencies": { + "@tailwindcss/forms": "^0.5.9", + "@tsconfig/node20": "^20.1.4", + "@types/node": "^20.14.5", + "@vitejs/plugin-vue": "^5.0.5", + "@vue/tsconfig": "^0.5.1", + "autoprefixer": "^10.4.19", + "npm-run-all2": "^6.2.0", + "postcss": "^8.4.40", + "tailwindcss": "^3.4.7", + "typescript": "~5.4.0", + "vite": "^5.3.1", + "vue-tsc": "^2.0.21" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@babel/parser": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.0.tgz", + "integrity": "sha512-CzdIU9jdP0dg7HdyB+bHvDJGagUv+qtzZt5rYCWwW6tITNqV9odjp6Qu41gkG0ca5UfdDUWrKkiAnHHdGRnOrA==", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@fortawesome/fontawesome-common-types": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.6.0.tgz", + "integrity": "sha512-xyX0X9mc0kyz9plIyryrRbl7ngsA9jz77mCZJsUkLl+ZKs0KWObgaEBoSgQiYWAsSmjz/yjl0F++Got0Mdp4Rw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/fontawesome-svg-core": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.6.0.tgz", + "integrity": "sha512-KHwPkCk6oRT4HADE7smhfsKudt9N/9lm6EJ5BVg0tD1yPA5hht837fB87F8pn15D8JfTqQOjhKTktwmLMiD7Kg==", + "license": "MIT", + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/free-brands-svg-icons": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.6.0.tgz", + "integrity": "sha512-1MPD8lMNW/earme4OQi1IFHtmHUwAKgghXlNwWi9GO7QkTfD+IIaYpIai4m2YJEzqfEji3jFHX1DZI5pbY/biQ==", + "license": "(CC-BY-4.0 AND MIT)", + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/free-regular-svg-icons": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.6.0.tgz", + "integrity": "sha512-Yv9hDzL4aI73BEwSEh20clrY8q/uLxawaQ98lekBx6t9dQKDHcDzzV1p2YtBGTtolYtNqcWdniOnhzB+JPnQEQ==", + "license": "(CC-BY-4.0 AND MIT)", + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/free-solid-svg-icons": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.6.0.tgz", + "integrity": "sha512-IYv/2skhEDFc2WGUcqvFJkeK39Q+HyPf5GHUrT/l2pKbtgEIv1al1TKd6qStR5OIwQdN1GZP54ci3y4mroJWjA==", + "license": "(CC-BY-4.0 AND MIT)", + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/vue-fontawesome": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@fortawesome/vue-fontawesome/-/vue-fontawesome-3.0.8.tgz", + "integrity": "sha512-yyHHAj4G8pQIDfaIsMvQpwKMboIZtcHTUvPqXjOHyldh1O1vZfH4W03VDPv5RvI9P6DLTzJQlmVgj9wCf7c2Fw==", + "license": "MIT", + "peerDependencies": { + "@fortawesome/fontawesome-svg-core": "~1 || ~6", + "vue": ">= 3.0.0 < 4" + } + }, + "node_modules/@headlessui/vue": { + "version": "1.7.23", + "resolved": "https://registry.npmjs.org/@headlessui/vue/-/vue-1.7.23.tgz", + "integrity": "sha512-JzdCNqurrtuu0YW6QaDtR2PIYCKPUWq28csDyMvN4zmGccmE7lz40Is6hc3LA4HFeCI7sekZ/PQMTNmn9I/4Wg==", + "license": "MIT", + "dependencies": { + "@tanstack/vue-virtual": "^3.0.0-beta.60" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/@heroicons/vue": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@heroicons/vue/-/vue-2.1.5.tgz", + "integrity": "sha512-IpqR72sFqFs55kyKfFS7tN+Ww6odFNeH/7UxycIOrlVYfj4WUGAdzQtLBnJspucSeqWFQsKM0g0YrgU655BEfA==", + "license": "MIT", + "peerDependencies": { + "vue": ">= 3" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.19.1.tgz", + "integrity": "sha512-XUXeI9eM8rMP8aGvii/aOOiMvTs7xlCosq9xCjcqI9+5hBxtjDpD+7Abm1ZhVIFE1J2h2VIg0t2DX/gjespC2Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.19.1.tgz", + "integrity": "sha512-V7cBw/cKXMfEVhpSvVZhC+iGifD6U1zJ4tbibjjN+Xi3blSXaj/rJynAkCFFQfoG6VZrAiP7uGVzL440Q6Me2Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@tailwindcss/forms": { + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.9.tgz", + "integrity": "sha512-tM4XVr2+UVTxXJzey9Twx48c1gcxFStqn1pQz0tRsX8o3DvxhN5oY5pvyAbUx7VTaZxpej4Zzvc6h+1RJBzpIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mini-svg-data-uri": "^1.2.3" + }, + "peerDependencies": { + "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1 || >= 4.0.0-alpha.20" + } + }, + "node_modules/@tanstack/virtual-core": { + "version": "3.10.7", + "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.10.7.tgz", + "integrity": "sha512-ND5dfsU0n9F4gROzwNNDJmg6y8n9pI8YWxtgbfJ5UcNn7Hx+MxEXtXcQ189tS7sh8pmCObgz2qSiyRKTZxT4dg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/vue-virtual": { + "version": "3.10.7", + "resolved": "https://registry.npmjs.org/@tanstack/vue-virtual/-/vue-virtual-3.10.7.tgz", + "integrity": "sha512-OSK1fkvz4GaBhF80KVmBsJZoMI9ncVaUU//pI8OqTdBnepw467zcuF2Y+Ia1VC0CPYfUEALyS8n4Ar0RI/7ASg==", + "license": "MIT", + "dependencies": { + "@tanstack/virtual-core": "3.10.7" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "vue": "^2.7.0 || ^3.0.0" + } + }, + "node_modules/@tsconfig/node20": { + "version": "20.1.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node20/-/node20-20.1.4.tgz", + "integrity": "sha512-sqgsT69YFeLWf5NtJ4Xq/xAF8p4ZQHlmGW74Nu2tD4+g5fAsposc4ZfaaPixVu4y01BEiDCWLRDCvDM5JOsRxg==", + "dev": true + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.14.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.13.tgz", + "integrity": "sha512-+bHoGiZb8UiQ0+WEtmph2IWQCjIqg8MDZMAV+ppRRhUZnquF5mQkP/9vpSwJClEiSM/C7fZZExPzfU0vJTyp8w==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@vitejs/plugin-vue": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.1.1.tgz", + "integrity": "sha512-sDckXxlHpMsjRQbAH9WanangrfrblsOd3pNifePs+FOHjJg1jfWq5L/P0PsBRndEt3nmdUnmvieP8ULDeX5AvA==", + "dev": true, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "vite": "^5.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@volar/language-core": { + "version": "2.4.0-alpha.18", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.0-alpha.18.tgz", + "integrity": "sha512-JAYeJvYQQROmVRtSBIczaPjP3DX4QW1fOqW1Ebs0d3Y3EwSNRglz03dSv0Dm61dzd0Yx3WgTW3hndDnTQqgmyg==", + "dev": true, + "dependencies": { + "@volar/source-map": "2.4.0-alpha.18" + } + }, + "node_modules/@volar/source-map": { + "version": "2.4.0-alpha.18", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.0-alpha.18.tgz", + "integrity": "sha512-MTeCV9MUwwsH0sNFiZwKtFrrVZUK6p8ioZs3xFzHc2cvDXHWlYN3bChdQtwKX+FY2HG6H3CfAu1pKijolzIQ8g==", + "dev": true + }, + "node_modules/@volar/typescript": { + "version": "2.4.0-alpha.18", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.0-alpha.18.tgz", + "integrity": "sha512-sXh5Y8sqGUkgxpMWUGvRXggxYHAVxg0Pa1C42lQZuPDrW6vHJPR0VCK8Sr7WJsAW530HuNQT/ZIskmXtxjybMQ==", + "dev": true, + "dependencies": { + "@volar/language-core": "2.4.0-alpha.18", + "path-browserify": "^1.0.1", + "vscode-uri": "^3.0.8" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.4.34", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.34.tgz", + "integrity": "sha512-Z0izUf32+wAnQewjHu+pQf1yw00EGOmevl1kE+ljjjMe7oEfpQ+BI3/JNK7yMB4IrUsqLDmPecUrpj3mCP+yJQ==", + "dependencies": { + "@babel/parser": "^7.24.7", + "@vue/shared": "3.4.34", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.0" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.4.34", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.34.tgz", + "integrity": "sha512-3PUOTS1h5cskdOJMExCu2TInXuM0j60DRPpSCJDqOCupCfUZCJoyQmKtRmA8EgDNZ5kcEE7vketamRZfrEuVDw==", + "dependencies": { + "@vue/compiler-core": "3.4.34", + "@vue/shared": "3.4.34" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.4.34", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.34.tgz", + "integrity": "sha512-x6lm0UrM03jjDXTPZgD9Ad8bIVD1ifWNit2EaWQIZB5CULr46+FbLQ5RpK7AXtDHGjx9rmvC7QRCTjsiGkAwRw==", + "dependencies": { + "@babel/parser": "^7.24.7", + "@vue/compiler-core": "3.4.34", + "@vue/compiler-dom": "3.4.34", + "@vue/compiler-ssr": "3.4.34", + "@vue/shared": "3.4.34", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.10", + "postcss": "^8.4.39", + "source-map-js": "^1.2.0" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.4.34", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.34.tgz", + "integrity": "sha512-8TDBcLaTrFm5rnF+Qm4BlliaopJgqJ28Nsrc80qazynm5aJO+Emu7y0RWw34L8dNnTRdcVBpWzJxhGYzsoVu4g==", + "dependencies": { + "@vue/compiler-dom": "3.4.34", + "@vue/shared": "3.4.34" + } + }, + "node_modules/@vue/compiler-vue2": { + "version": "2.7.16", + "resolved": "https://registry.npmjs.org/@vue/compiler-vue2/-/compiler-vue2-2.7.16.tgz", + "integrity": "sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==", + "dev": true, + "dependencies": { + "de-indent": "^1.0.2", + "he": "^1.2.0" + } + }, + "node_modules/@vue/devtools-api": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.3.tgz", + "integrity": "sha512-0MiMsFma/HqA6g3KLKn+AGpL1kgKhFWszC9U29NfpWK5LE7bjeXxySWJrOJ77hBz+TBrBQ7o4QJqbPbqbs8rJw==" + }, + "node_modules/@vue/language-core": { + "version": "2.0.29", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-2.0.29.tgz", + "integrity": "sha512-o2qz9JPjhdoVj8D2+9bDXbaI4q2uZTHQA/dbyZT4Bj1FR9viZxDJnLcKVHfxdn6wsOzRgpqIzJEEmSSvgMvDTQ==", + "dev": true, + "dependencies": { + "@volar/language-core": "~2.4.0-alpha.18", + "@vue/compiler-dom": "^3.4.0", + "@vue/compiler-vue2": "^2.7.16", + "@vue/shared": "^3.4.0", + "computeds": "^0.0.1", + "minimatch": "^9.0.3", + "muggle-string": "^0.4.1", + "path-browserify": "^1.0.1" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@vue/reactivity": { + "version": "3.4.34", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.34.tgz", + "integrity": "sha512-ua+Lo+wBRlBEX9TtgPOShE2JwIO7p6BTZ7t1KZVPoaBRfqbC7N3c8Mpzicx173fXxx5VXeU6ykiHo7WgLzJQDA==", + "dependencies": { + "@vue/shared": "3.4.34" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.4.34", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.34.tgz", + "integrity": "sha512-PXhkiRPwcPGJ1BnyBZFI96GfInCVskd0HPNIAZn7i3YOmLbtbTZpB7/kDTwC1W7IqdGPkTVC63IS7J2nZs4Ebg==", + "dependencies": { + "@vue/reactivity": "3.4.34", + "@vue/shared": "3.4.34" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.4.34", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.34.tgz", + "integrity": "sha512-dXqIe+RqFAK2Euak4UsvbIupalrhc67OuQKpD7HJ3W2fv8jlqvI7szfBCsAEcE8o/wyNpkloxB6J8viuF/E3gw==", + "dependencies": { + "@vue/reactivity": "3.4.34", + "@vue/runtime-core": "3.4.34", + "@vue/shared": "3.4.34", + "csstype": "^3.1.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.4.34", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.34.tgz", + "integrity": "sha512-GeyEUfMVRZMD/mZcNONEqg7MiU10QQ1DB3O/Qr6+8uXpbwdlmVgQ5Qs1/ZUAFX1X2UUtqMoGrDRbxdWfOJFT7Q==", + "dependencies": { + "@vue/compiler-ssr": "3.4.34", + "@vue/shared": "3.4.34" + }, + "peerDependencies": { + "vue": "3.4.34" + } + }, + "node_modules/@vue/shared": { + "version": "3.4.34", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.34.tgz", + "integrity": "sha512-x5LmiRLpRsd9KTjAB8MPKf0CDPMcuItjP0gbNqFCIgL1I8iYp4zglhj9w9FPCdIbHG2M91RVeIbArFfFTz9I3A==" + }, + "node_modules/@vue/tsconfig": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@vue/tsconfig/-/tsconfig-0.5.1.tgz", + "integrity": "sha512-VcZK7MvpjuTPx2w6blwnwZAu5/LgBUtejFOi3pPGQFXQN5Ela03FUtd2Qtg4yWGGissVL0dr6Ro1LfOFh+PCuQ==", + "dev": true + }, + "node_modules/air-datepicker": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/air-datepicker/-/air-datepicker-3.5.3.tgz", + "integrity": "sha512-Elf9gLhv/jidN1+TfeRJYMQRUfYx5apXw2dY5DuAMPRnNtQ4Iw9fTTJK772osmXSUB9xQ2Y8Q1Pt6pgBOQLPQw==", + "license": "MIT" + }, + "node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true + }, + "node_modules/autoprefixer": { + "version": "10.4.19", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.19.tgz", + "integrity": "sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "browserslist": "^4.23.0", + "caniuse-lite": "^1.0.30001599", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.2.tgz", + "integrity": "sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001640", + "electron-to-chromium": "^1.4.820", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.1.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001643", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001643.tgz", + "integrity": "sha512-ERgWGNleEilSrHM6iUz/zJNSQTP8Mr21wDWpdgvRwcTXGAq6jMtOUPP4dqFPTdKqZ2wKTdtB+uucZ3MRpAUSmg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/computeds": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/computeds/-/computeds-0.0.1.tgz", + "integrity": "sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/date-fns": { + "version": "4.0.0-beta.1", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.0.0-beta.1.tgz", + "integrity": "sha512-EjMXEgaR2r/Ff8aLwg8OtPnMq3caEANXuYVDz3F7UnL0f/sjeQW+mwQAS2iwziipMSi7kqc9tdfBmGAefhrY+A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, + "node_modules/de-indent": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", + "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", + "dev": true + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/electron-to-chromium": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.2.tgz", + "integrity": "sha512-kc4r3U3V3WLaaZqThjYz/Y6z8tJe+7K0bbjUVo3i+LWIypVdMx5nXCkwRe6SWbY6ILqLdc1rKcKmr3HoH7wjSQ==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/foreground-child": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", + "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "dev": true, + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.0.tgz", + "integrity": "sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==", + "dev": true, + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jiti": { + "version": "1.21.6", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", + "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", + "dev": true, + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.2.tgz", + "integrity": "sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true + }, + "node_modules/luxon": { + "version": "1.28.1", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.28.1.tgz", + "integrity": "sha512-gYHAa180mKrNIUJCbwpmD0aTu9kV0dREDrwNnuyFAsO1Wt0EVYSZelPnJlbj9HplzXX/YWXHFTL45kvZ53M0pw==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/magic-string": { + "version": "0.30.10", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", + "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + } + }, + "node_modules/memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mini-svg-data-uri": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz", + "integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==", + "dev": true, + "license": "MIT", + "bin": { + "mini-svg-data-uri": "cli.js" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/muggle-string": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz", + "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", + "dev": true + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-releases": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "dev": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-normalize-package-bin": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", + "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-run-all2": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/npm-run-all2/-/npm-run-all2-6.2.2.tgz", + "integrity": "sha512-Q+alQAGIW7ZhKcxLt8GcSi3h3ryheD6xnmXahkMRVM5LYmajcUrSITm8h+OPC9RYWMV2GR0Q1ntTUCfxaNoOJw==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.2.1", + "cross-spawn": "^7.0.3", + "memorystream": "^0.3.1", + "minimatch": "^9.0.0", + "pidtree": "^0.6.0", + "read-package-json-fast": "^3.0.2", + "shell-quote": "^1.7.3" + }, + "bin": { + "npm-run-all": "bin/npm-run-all/index.js", + "npm-run-all2": "bin/npm-run-all/index.js", + "run-p": "bin/run-p/index.js", + "run-s": "bin/run-s/index.js" + }, + "engines": { + "node": "^14.18.0 || ^16.13.0 || >=18.0.0", + "npm": ">= 8" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", + "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", + "dev": true + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/picocolors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true, + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/postcss": { + "version": "8.4.40", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.40.tgz", + "integrity": "sha512-YF2kKIUzAofPMpfH6hOi2cGnv/HrUlfucspc7pDyvv7kGdqXrfj8SCl/t8owkEgKEuu8ZcRjSOxFxVLqwChZ2Q==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.1", + "source-map-js": "^1.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "dev": true, + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-load-config/node_modules/lilconfig": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.1.tgz", + "integrity": "sha512-b4dlw/9V8A71rLIDsSwVmak9z2DuBUB7CA1/wSdelNEzqsjoSPeADTWNO09lpH49Diy3/JIZ2bSPB1dI3LJCHg==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/read-package-json-fast": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz", + "integrity": "sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==", + "dev": true, + "dependencies": { + "json-parse-even-better-errors": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rollup": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.19.1.tgz", + "integrity": "sha512-K5vziVlg7hTpYfFBI+91zHBEMo6jafYXpkMlqZjg7/zhIG9iHqazBf4xz9AVdjS9BruRn280ROqLI7G3OFRIlw==", + "dev": true, + "dependencies": { + "@types/estree": "1.0.5" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.19.1", + "@rollup/rollup-android-arm64": "4.19.1", + "@rollup/rollup-darwin-arm64": "4.19.1", + "@rollup/rollup-darwin-x64": "4.19.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.19.1", + "@rollup/rollup-linux-arm-musleabihf": "4.19.1", + "@rollup/rollup-linux-arm64-gnu": "4.19.1", + "@rollup/rollup-linux-arm64-musl": "4.19.1", + "@rollup/rollup-linux-powerpc64le-gnu": "4.19.1", + "@rollup/rollup-linux-riscv64-gnu": "4.19.1", + "@rollup/rollup-linux-s390x-gnu": "4.19.1", + "@rollup/rollup-linux-x64-gnu": "4.19.1", + "@rollup/rollup-linux-x64-musl": "4.19.1", + "@rollup/rollup-win32-arm64-msvc": "4.19.1", + "@rollup/rollup-win32-ia32-msvc": "4.19.1", + "@rollup/rollup-win32-x64-msvc": "4.19.1", + "fsevents": "~2.3.2" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/source-map-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tailwindcss": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.7.tgz", + "integrity": "sha512-rxWZbe87YJb4OcSopb7up2Ba4U82BoiSGUdoDr3Ydrg9ckxFS/YWsvhN323GMcddgU65QRy7JndC7ahhInhvlQ==", + "dev": true, + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.0", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.0", + "lilconfig": "^2.1.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.23", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.1", + "postcss-nested": "^6.0.1", + "postcss-selector-parser": "^6.0.11", + "resolve": "^1.22.2", + "sucrase": "^3.32.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true + }, + "node_modules/typescript": { + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "devOptional": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/update-browserslist-db": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", + "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.2", + "picocolors": "^1.0.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/vite": { + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.3.5.tgz", + "integrity": "sha512-MdjglKR6AQXQb9JGiS7Rc2wC6uMjcm7Go/NHNO63EwiJXfuk9PgqiP/n5IDJCziMkfw9n4Ubp7lttNwz+8ZVKA==", + "dev": true, + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.39", + "rollup": "^4.13.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vscode-uri": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", + "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==", + "dev": true + }, + "node_modules/vue": { + "version": "3.4.34", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.34.tgz", + "integrity": "sha512-VZze05HWlA3ItreQ/ka7Sx7PoD0/3St8FEiSlSTVgb6l4hL+RjtP2/8g5WQBzZgyf8WG2f+g1bXzC7zggLhAJA==", + "dependencies": { + "@vue/compiler-dom": "3.4.34", + "@vue/compiler-sfc": "3.4.34", + "@vue/runtime-dom": "3.4.34", + "@vue/server-renderer": "3.4.34", + "@vue/shared": "3.4.34" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-luxon": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/vue-luxon/-/vue-luxon-0.10.0.tgz", + "integrity": "sha512-edMqK3qfWNze9z7Upbkb6RSI5XFFwaU3LwD6ZPJJPBhinTg1VBH7Rn8qNi5+5GmHMcbp2ybnOWm78m5lTjznFw==", + "license": "MIT", + "dependencies": { + "luxon": "^1.25.0" + } + }, + "node_modules/vue-moment": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/vue-moment/-/vue-moment-4.1.0.tgz", + "integrity": "sha512-Gzisqpg82ItlrUyiD9d0Kfru+JorW2o4mQOH06lEDZNgxci0tv/fua1Hl0bo4DozDV2JK1r52Atn/8QVCu8qQw==", + "license": "MIT", + "dependencies": { + "moment": "^2.19.2" + }, + "peerDependencies": { + "vue": ">=1.x.x" + } + }, + "node_modules/vue-router": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.4.0.tgz", + "integrity": "sha512-HB+t2p611aIZraV2aPSRNXf0Z/oLZFrlygJm+sZbdJaW6lcFqEDQwnzUBXn+DApw+/QzDU/I9TeWx9izEjTmsA==", + "dependencies": { + "@vue/devtools-api": "^6.5.1" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/vue-toastification": { + "version": "2.0.0-rc.5", + "resolved": "https://registry.npmjs.org/vue-toastification/-/vue-toastification-2.0.0-rc.5.tgz", + "integrity": "sha512-q73e5jy6gucEO/U+P48hqX+/qyXDozAGmaGgLFm5tXX4wJBcVsnGp4e/iJqlm9xzHETYOilUuwOUje2Qg1JdwA==", + "license": "MIT", + "peerDependencies": { + "vue": "^3.0.2" + } + }, + "node_modules/vue-tsc": { + "version": "2.0.29", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-2.0.29.tgz", + "integrity": "sha512-MHhsfyxO3mYShZCGYNziSbc63x7cQ5g9kvijV7dRe1TTXBRLxXyL0FnXWpUF1xII2mJ86mwYpYsUmMwkmerq7Q==", + "dev": true, + "dependencies": { + "@volar/typescript": "~2.4.0-alpha.18", + "@vue/language-core": "2.0.29", + "semver": "^7.5.4" + }, + "bin": { + "vue-tsc": "bin/vue-tsc.js" + }, + "peerDependencies": { + "typescript": ">=5.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yaml": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.0.tgz", + "integrity": "sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==", + "dev": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + } + } +} diff --git a/chorechef_frontend/package.json b/chorechef_frontend/package.json new file mode 100644 index 0000000000000000000000000000000000000000..dd4d58a564c05d7951d6219016931ce123a7bc97 --- /dev/null +++ b/chorechef_frontend/package.json @@ -0,0 +1,44 @@ +{ + "name": "chorechef", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "@fortawesome/fontawesome-svg-core": "^6.6.0", + "@fortawesome/free-brands-svg-icons": "^6.6.0", + "@fortawesome/free-regular-svg-icons": "^6.6.0", + "@fortawesome/free-solid-svg-icons": "^6.6.0", + "@fortawesome/vue-fontawesome": "^3.0.8", + "@headlessui/vue": "^1.7.23", + "@heroicons/vue": "^2.1.5", + "air-datepicker": "^3.5.3", + "date-fns": "^4.0.0-beta.1", + "moment": "^2.30.1", + "vue": "^3.4.29", + "vue-luxon": "^0.10.0", + "vue-moment": "^4.1.0", + "vue-router": "^4.3.3", + "vue-toastification": "^2.0.0-rc.5" + }, + "devDependencies": { + "@tailwindcss/forms": "^0.5.9", + "@tsconfig/node20": "^20.1.4", + "@types/node": "^20.14.5", + "@vitejs/plugin-vue": "^5.0.5", + "@vue/tsconfig": "^0.5.1", + "autoprefixer": "^10.4.19", + "npm-run-all2": "^6.2.0", + "postcss": "^8.4.40", + "tailwindcss": "^3.4.7", + "typescript": "~5.4.0", + "vite": "^5.3.1", + "vue-tsc": "^2.0.21" + } +} diff --git a/chorechef_frontend/postcss.config.js b/chorechef_frontend/postcss.config.js new file mode 100644 index 0000000000000000000000000000000000000000..2aa7205d4b402a1bdfbe07110c61df920b370066 --- /dev/null +++ b/chorechef_frontend/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/chorechef_frontend/public/favicon.ico b/chorechef_frontend/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..5ea54d7a9ad90c4b613d53051d5c0f0bdbd1e2e4 Binary files /dev/null and b/chorechef_frontend/public/favicon.ico differ diff --git a/chorechef_frontend/public/favicon.png b/chorechef_frontend/public/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..24bfbd7f547d533b80d9471ecdce02295711230b Binary files /dev/null and b/chorechef_frontend/public/favicon.png differ diff --git a/chorechef_frontend/src/App.vue b/chorechef_frontend/src/App.vue new file mode 100644 index 0000000000000000000000000000000000000000..0c2c08d593b023724403d80cef27f60cfbbe6bf3 --- /dev/null +++ b/chorechef_frontend/src/App.vue @@ -0,0 +1,51 @@ +<script setup lang="ts"> +import { RouterLink, RouterView } from "vue-router"; +import Dashboard from "./components/Dashboard.vue"; +import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; +import { faCog } from "@fortawesome/free-solid-svg-icons"; +</script> + +<template> + <header> + <div class="wrapper flex flex-row bg-neutral-200"> + <Dashboard /> + + <nav class="flex flex-row items-center grow gap-8 pl-8"> + <RouterLink + to="/" + class="flex items-center p-2 rounded-xl hover:cursor-pointer hover:text-neutral-700 hover:drop-shadow-lg transition" + >Dashboard</RouterLink + > + <RouterLink + to="/mealplan" + class="flex items-center p-2 rounded-xl hover:cursor-pointer hover:text-neutral-700 hover:drop-shadow-lg transition" + >Essensplan</RouterLink + > + <RouterLink + to="/chores" + class="flex items-center p-2 rounded-xl hover:cursor-pointer hover:text-neutral-700 hover:drop-shadow-lg transition" + >Aufgaben</RouterLink + > + </nav> + <div class="filler"></div> + <RouterLink + to="/settings" + class="flex items-center px-2 my-2 mr-8 rounded-xl hover:cursor-pointer hover:text-neutral-700 hover:drop-shadow-lg transition" + > + <div class="text-2xl items-center"> + <FontAwesomeIcon :icon="faCog" /> + </div> + </RouterLink> + </div> + </header> + <RouterView /> +</template> +<style lang="css"> +.router-link-exact-active { + font-weight: bold; + background-color: #d1d5db; + box-shadow: + 0 20px 25px -5px rgb(0 0 0 / 0.1), + 0 8px 10px -6px rgb(0 0 0 / 0.1); +} +</style> diff --git a/chorechef_frontend/src/assets/icons/arrow-left.svg b/chorechef_frontend/src/assets/icons/arrow-left.svg new file mode 100644 index 0000000000000000000000000000000000000000..a646d1ccf2b7e4d78c82818ce26f275af1ec09e9 --- /dev/null +++ b/chorechef_frontend/src/assets/icons/arrow-left.svg @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + width="512" + height="512" + viewBox="0 0 512 512" + version="1.1" + id="svg1" + sodipodi:docname="arrow-left.svg" + inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <sodipodi:namedview + id="namedview1" + pagecolor="#ffffff" + bordercolor="#999999" + borderopacity="1" + inkscape:showpageshadow="2" + inkscape:pageopacity="0" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1" + inkscape:document-units="px" + inkscape:zoom="0.70710678" + inkscape:cx="135.7645" + inkscape:cy="0.70710678" + inkscape:window-width="1368" + inkscape:window-height="843" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="layer1" /> + <defs + id="defs1" /> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1"> + <circle + id="path1" + style="fill:#000000;stroke:#000000" + cx="2625.9294" + cy="205.98904" + r="2.8478267" /> + <circle + id="path4" + style="fill:#000000;stroke:#000000" + cx="2289.0151" + cy="-92.03437" + r="2.8478267" /> + <path + id="path6" + style="fill:#000000" + d="m 481.17559,42.546875 c 0.10678,0.0025 0.2139,0.0079 0.32031,0.01758 0.23486,0.02139 0.4312,0.06746 0.66211,0.113281 0.25881,0.05896 0.5108,0.136444 0.75977,0.22461 0.008,0.004 0.0157,0.0077 0.0234,0.01172 0.21093,0.141159 0.41991,0.285522 0.62695,0.431641 0.76867,2.738626 1.25985,4.700927 1.58594,6.8125 0.007,0.297067 0.0157,0.593558 0.0273,0.890625 0.015,0.505097 0.038,1.010969 0.0645,1.515625 0.0349,0.540312 0.0502,1.08155 0.0977,1.621094 0.0278,0.413725 0.0598,0.827484 0.0996,1.240234 0.0134,0.410002 0.0253,0.82025 0.0312,1.230469 0.008,0.327728 0.0366,0.654838 0.041,0.982422 0.0245,0.175436 0.0171,0.285218 0.10937,0.302734 3e-4,0.02083 0.002,0.04167 0.002,0.0625 0.031,0.292497 0.0505,0.585039 0.0645,0.878906 0.0133,0.306546 0.0234,0.613357 0.0391,0.919922 0.005,0.155752 0.0219,0.310772 0.041,0.464844 -0.0117,1.076553 -0.0407,2.154099 0.0625,3.22461 0.43494,4.510045 1.586,8.931409 2.02149,13.441406 0.5331,5.520915 0.56309,11.079704 0.88085,16.617187 0.40418,7.043215 0.85693,14.083205 1.28516,21.124995 0.32731,8.60911 1.04569,17.21298 0.98242,25.82813 -0.0533,7.25913 -2.65105,46.802 -3.11133,53.65625 -4.49447,66.92986 0.61264,-9.60712 -4.56835,58.63476 -0.78366,10.322 -1.3783,20.65765 -2.06836,30.98633 -0.92891,10.12176 -1.86735,20.24263 -2.78711,30.36523 -0.88138,9.70005 -1.64031,19.41066 -2.61719,29.10157 -1.99373,19.77839 -3.65741,32.32055 -6.30469,51.75976 -0.95708,7.028 -1.78085,14.07702 -2.96484,21.07031 -0.93437,5.51892 -2.25727,10.96501 -3.38672,16.44727 -1.89626,9.99363 -3.12564,14.04167 -3.375,23.92188 -0.2379,9.4262 1.3315,18.79448 1.94726,28.16796 0.15865,2.41501 0.14015,4.83864 0.21094,7.25782 -0.11813,1.96906 0.052,3.97768 -0.35351,5.9082 -0.56513,2.69048 -2.6512,6.65825 -6.20508,6.5 -2.71964,-0.12111 -5.21096,-1.71024 -7.57032,-3.06836 -4.38133,-2.52205 -13.01734,-10.6612 -16.17773,-13.48047 -3.07815,-3.27348 -6.02962,-6.67062 -9.23438,-9.82031 -3.71423,-3.65045 -7.63623,-7.08324 -11.50781,-10.56641 -7.5234,-6.76863 -18.67988,-16.69057 -26.79492,-22.62695 -7.01174,-5.12928 -27.86904,-18.2894 -34.95703,-22.81836 -16.9684,-10.26397 -20.49321,-12.59268 -37.83789,-22.28906 -6.33578,-3.54196 -12.7966,-6.85706 -19.125,-10.41211 -9.24181,-5.19166 -22.64578,-13.6634 -32.51172,-18.01172 -6.49513,-2.86267 -13.29546,-4.97357 -19.94336,-7.46094 -10.80441,-5.09688 -25.72186,-12.36939 -36.86523,-16.67773 -7.18641,-2.77847 -14.55987,-5.04538 -21.83985,-7.56836 -7.32703,-2.81296 -14.68748,-5.53931 -21.98047,-8.43945 -15.80201,-6.284 -22.89994,-9.50162 -38.125,-16.11914 -8.36708,-4.63523 -17.77715,-7.17347 -26.191397,-11.72071 -1.49931,-0.81026 -2.51814,-2.3366 -3.99024,-3.19531 -2.0323,-1.18549 -4.30141,-1.90661 -6.43945,-2.88867 -5.0955,-2.3405 -4.75793,-2.25478 -9.88867,-4.95703 -0.67137,-1.11627 -1.83321,-2.05761 -2.01367,-3.34766 -0.71709,-5.12629 3.53902,-9.04049 6.66015,-12.30078 3.9962,-4.17438 7.1673,-7.17015 11.41406,-11.30274 11.562597,-9.41896 23.888167,-17.8272 37.119137,-24.72851 3.61782,-1.88706 7.3382,-3.57292 10.99805,-5.37695 3.95046,-1.9473 7.88928,-3.91804 11.83399,-5.87696 13.85228,-6.87939 27.59737,-13.97398 41.51562,-20.7207 5.92737,-2.87324 23.13726,-10.8227 28.9707,-14.12109 5.10466,-2.88634 9.93223,-6.23707 14.89844,-9.35547 23.61785,-16.82416 48.47588,-31.8934 73.86914,-45.875 11.6464,-6.41258 23.45552,-12.52827 35.17578,-18.80469 21.55947,-10.48441 41.57921,-23.690781 61.82222,-36.437501 15.63016,-9.842083 16.08347,-10.015342 31.7168,-19.447265 9.48522,-4.607574 17.71173,-11.544141 27.16797,-16.210938 2.63469,-1.300255 5.4269,-2.237362 8.20898,-3.199218 0.006,-0.0149 0.0119,-0.03404 0.0176,-0.04883 0.0409,-0.01192 0.0818,-0.02442 0.12305,-0.03516 0.29068,-0.07691 0.57807,-0.162751 0.86914,-0.238281 0.39072,-0.09743 0.78412,-0.189842 1.16992,-0.306641 0.44929,-0.115 0.90183,-0.224939 1.32031,-0.43164 0.3797,-0.191982 0.74414,-0.412686 1.09571,-0.652344 0.31464,-0.214747 0.61698,-0.446502 0.9375,-0.652344 0.0549,-0.0268 0.11255,-0.04546 0.16797,-0.07031 0.23882,-0.02127 0.47737,-0.04059 0.71679,-0.05469 0.31952,-0.0069 0.64058,-0.02518 0.96094,-0.01758 z m -14.54492,35.964844 c -3.65087,2.918638 -7.52891,5.990737 -9.33789,7.433593 -15.00823,10.760744 -15.54272,11.600186 -31.60352,21.226568 -20.64752,12.37543 -42.41225,22.91211 -62.16406,36.77539 -36.04918,22.69648 -71.56888,46.70177 -110.56836,64.16406 -5.70349,2.69221 -11.44483,5.30707 -17.11133,8.07617 -15.42875,7.53961 -13.75597,7.46335 -29.45899,14.45117 -9.99878,4.44948 -20.2682,8.41917 -30.53906,12.18945 -4.58751,1.68404 -9.21492,3.25966 -13.82226,4.88868 -4.04834,1.46474 -8.14081,2.80995 -12.14454,4.39258 -17.00003,6.7199 -32.82668,16.00976 -48.39648,25.49023 -3.925606,1.91783 -10.259516,4.99777 -14.466796,7.09766 1.27244,-0.007 2.5461,-0.0396 3.81446,0.0508 15.232166,1.08501 30.287756,3.64053 45.054676,7.54297 18.62714,5.44973 22.73846,6.21799 41.29688,13.51757 27.55514,10.83829 15.75534,7.10574 42.14844,19.49024 6.51651,3.05779 30.96703,13.34 37.58789,16.14453 6.12184,3.35421 12.09407,6.99653 18.36523,10.0625 11.80393,5.77088 24.38991,9.83895 36.21875,15.55859 6.76193,3.26965 13.33874,6.91309 19.89258,10.58203 18.83162,10.54228 20.86113,12.34426 38.88867,24.21094 5.99972,4.48937 12.17979,8.74455 17.99805,13.4668 5.47414,4.44295 10.65317,9.24316 15.85156,14.00586 9.80299,8.98128 17.24612,16.11523 25.64453,26.37304 3.39484,4.14647 6.4258,8.57735 9.54688,12.9336 2.06422,2.8812 4.04278,5.82375 6.04296,8.75 -2.35507,-15.57309 -2.06338,-31.4689 -4.52148,-47.04688 -0.60038,-5.66986 -1.40211,-11.32216 -1.80078,-17.00976 -0.502,-7.16169 -0.64633,-14.3447 -0.89844,-21.51953 -0.6393,-18.19439 -1.12921,-34.23186 -0.73242,-52.52344 0.49623,-22.87524 1.78976,-37.32595 3.39258,-60.25195 3.33773,-26.81815 4.18534,-33.63693 7.47461,-60.03711 1.15241,-9.24939 2.42343,-18.48484 3.45898,-27.74805 0.97994,-8.7658 1.79055,-17.54969 2.58789,-26.33398 0.78636,-8.66343 1.10375,-17.37369 2.16407,-26.00782 1.0344,-8.4231 2.74333,-16.74828 4.11523,-25.12304 1.2217,-6.87597 2.48914,-13.74484 3.66407,-20.62891 0.83179,-4.873651 1.45979,-9.783689 2.35742,-14.644531 z" /> + <path + style="fill:#000000" + d="m 466.21349,77.679688 c 5.20187,3.266294 0.40472,10.30491 0.70984,15.16384 -4.52616,26.307312 -8.98424,52.510992 -10.6439,79.182892 -6.02047,61.00092 -16.90491,121.71299 -16.05032,183.16499 -0.0707,32.01085 1.76424,63.72639 5.3803,95.45782 0.19064,8.28992 2.17452,16.74153 1.73493,24.89765 -4.12225,5.13687 -8.40113,-2.5937 -10.62304,-5.66993 -36.78337,-50.60618 -91.53232,-85.20998 -148.31897,-109.71176 -19.99215,-8.48238 -38.77654,-19.53839 -59.02156,-27.48768 -26.17033,-12.1058 -51.9659,-25.37614 -79.81442,-33.34183 -19.62906,-6.10616 -39.76062,-10.17528 -60.292315,-12.0349 -6.61742,-3.02435 0.93093,-8.03122 4.87305,-9.05859 23.304125,-13.34361 46.595565,-27.23772 72.460835,-35.1084 34.61369,-11.66592 66.83499,-29.11373 99.85947,-44.71582 51.92433,-26.01609 98.58566,-61.51214 149.74567,-89.10991 16.79933,-9.13242 32.03337,-20.744986 47.79144,-31.442826 0.70223,-0.391313 1.45377,-0.230392 2.20899,-0.185546 z" + id="path9" /> + </g> +</svg> diff --git a/chorechef_frontend/src/assets/icons/arrow-right.svg b/chorechef_frontend/src/assets/icons/arrow-right.svg new file mode 100644 index 0000000000000000000000000000000000000000..496c80699d808b1ceb9ab53efe9efb6ef7e9da54 --- /dev/null +++ b/chorechef_frontend/src/assets/icons/arrow-right.svg @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + width="512" + height="512" + viewBox="0 0 512 512" + version="1.1" + id="svg1" + inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)" + sodipodi:docname="arrow_back.svg" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <sodipodi:namedview + id="namedview1" + pagecolor="#ffffff" + bordercolor="#999999" + borderopacity="1" + inkscape:showpageshadow="2" + inkscape:pageopacity="0" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1" + inkscape:document-units="px" + inkscape:zoom="0.5" + inkscape:cx="67" + inkscape:cy="69" + inkscape:window-width="1368" + inkscape:window-height="843" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="layer1" /> + <defs + id="defs1" /> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1"> + <circle + id="path1" + style="fill:#000000;stroke:#000000" + cx="2625.9294" + cy="205.98904" + r="2.8478267" /> + <circle + id="path4" + style="fill:#000000;stroke:#000000" + cx="2289.0151" + cy="-92.03437" + r="2.8478267" /> + <path + id="path6" + style="fill:#000000" + d="m 74.177734,42.546875 c -0.106785,0.0025 -0.213905,0.0079 -0.320312,0.01758 -0.234863,0.02139 -0.431203,0.06746 -0.66211,0.113281 -0.25881,0.05896 -0.510795,0.136444 -0.759765,0.22461 -0.0077,0.004 -0.0157,0.0077 -0.02344,0.01172 -0.210936,0.141159 -0.419918,0.285522 -0.626953,0.431641 -0.768669,2.738626 -1.259854,4.700927 -1.585937,6.8125 -0.0075,0.297067 -0.01573,0.593558 -0.02734,0.890625 -0.01497,0.505097 -0.03801,1.010969 -0.06445,1.515625 -0.03493,0.540312 -0.05017,1.08155 -0.09766,1.621094 -0.02782,0.413725 -0.05983,0.827484 -0.09961,1.240234 -0.01339,0.410002 -0.02528,0.82025 -0.03125,1.230469 -0.0078,0.327728 -0.0366,0.654838 -0.04102,0.982422 -0.02454,0.175436 -0.01713,0.285218 -0.109375,0.302734 -3.03e-4,0.02083 -0.0017,0.04167 -0.002,0.0625 -0.03101,0.292497 -0.05045,0.585039 -0.06445,0.878906 -0.01329,0.306546 -0.0234,0.613357 -0.03906,0.919922 -0.0053,0.155752 -0.02191,0.310772 -0.04102,0.464844 0.01166,1.076553 0.04074,2.154099 -0.0625,3.22461 -0.434942,4.510045 -1.585998,8.931409 -2.021484,13.441406 -0.533106,5.520915 -0.563097,11.079704 -0.880859,16.617187 -0.404173,7.043219 -0.856929,14.083209 -1.285157,21.124999 -0.327304,8.60911 -1.045684,17.21298 -0.982422,25.82813 0.0533,7.25913 2.651053,46.802 3.111329,53.65625 4.494475,66.92986 -0.612639,-9.60712 4.568359,58.63476 0.783656,10.322 1.378293,20.65765 2.068359,30.98633 0.928909,10.12176 1.867347,20.24263 2.78711,30.36523 0.881372,9.70005 1.640309,19.41066 2.617187,29.10157 1.993732,19.77839 3.657405,32.32055 6.304688,51.75976 0.957085,7.028 1.780851,14.07702 2.964843,21.07031 0.934369,5.51892 2.257273,10.96501 3.386719,16.44727 1.89626,9.99363 3.12564,14.04167 3.375,23.92188 0.237903,9.4262 -1.331502,18.79448 -1.947265,28.16796 -0.158647,2.41501 -0.140142,4.83864 -0.210938,7.25782 0.118132,1.96906 -0.05198,3.97768 0.353516,5.9082 0.565123,2.69048 2.651197,6.65825 6.205078,6.5 2.719636,-0.12111 5.210956,-1.71024 7.570316,-3.06836 4.38133,-2.52205 13.01734,-10.6612 16.17773,-13.48047 3.07815,-3.27348 6.02962,-6.67062 9.23438,-9.82031 3.71423,-3.65045 7.63623,-7.08324 11.50781,-10.56641 7.5234,-6.76863 18.67988,-16.69057 26.79492,-22.62695 7.01174,-5.12928 27.86904,-18.2894 34.95703,-22.81836 16.9684,-10.26397 20.49321,-12.59268 37.83789,-22.28906 6.33578,-3.54196 12.7966,-6.85706 19.125,-10.41211 9.24181,-5.19166 22.64578,-13.6634 32.51172,-18.01172 6.49513,-2.86267 13.29546,-4.97357 19.94336,-7.46094 10.80441,-5.09688 25.72186,-12.36939 36.86523,-16.67773 7.18641,-2.77847 14.55987,-5.04538 21.83985,-7.56836 7.32703,-2.81296 14.68748,-5.53931 21.98047,-8.43945 15.80201,-6.284 22.89994,-9.50162 38.125,-16.11914 8.36708,-4.63523 17.77715,-7.17347 26.1914,-11.72071 1.49931,-0.81026 2.51814,-2.3366 3.99024,-3.19531 2.0323,-1.18549 4.30141,-1.90661 6.43945,-2.88867 5.0955,-2.3405 4.75793,-2.25478 9.88867,-4.95703 0.67137,-1.11627 1.83321,-2.05761 2.01367,-3.34766 0.71709,-5.12629 -3.53902,-9.04049 -6.66015,-12.30078 -3.9962,-4.17438 -7.1673,-7.17015 -11.41406,-11.30274 -11.5626,-9.41896 -23.88817,-17.8272 -37.11914,-24.72851 -3.61782,-1.88706 -7.3382,-3.57292 -10.99805,-5.37695 -3.95046,-1.9473 -7.88928,-3.91804 -11.83399,-5.87696 -13.85228,-6.87939 -27.59737,-13.97398 -41.51562,-20.7207 -5.92737,-2.87324 -23.13726,-10.8227 -28.9707,-14.12109 -5.10466,-2.88634 -9.93223,-6.23707 -14.89844,-9.35547 -23.61785,-16.82416 -48.47588,-31.8934 -73.86914,-45.875 -11.6464,-6.41258 -23.45552,-12.52827 -35.17578,-18.80469 C 188.91314,109.8652 168.8934,96.658829 148.65039,83.912109 133.02023,74.070026 132.56692,73.896767 116.93359,64.464844 107.44837,59.85727 99.221862,52.920703 89.765625,48.253906 c -2.634688,-1.300255 -5.426904,-2.237362 -8.208984,-3.199218 -0.0057,-0.0149 -0.01194,-0.03404 -0.01758,-0.04883 -0.04089,-0.01192 -0.08179,-0.02442 -0.123046,-0.03516 -0.290686,-0.07691 -0.57807,-0.162751 -0.869141,-0.238281 -0.390724,-0.09743 -0.784121,-0.189842 -1.169922,-0.306641 -0.449287,-0.115 -0.90183,-0.224939 -1.320312,-0.43164 -0.379696,-0.191982 -0.744138,-0.412686 -1.095703,-0.652344 -0.314646,-0.214747 -0.616986,-0.446502 -0.9375,-0.652344 -0.05485,-0.0268 -0.11255,-0.04546 -0.167969,-0.07031 -0.238822,-0.02127 -0.477371,-0.04059 -0.716797,-0.05469 -0.319518,-0.0069 -0.640582,-0.02518 -0.960938,-0.01758 z m 14.544922,35.964844 c 3.650864,2.918638 7.528904,5.990737 9.337891,7.433593 15.008223,10.760744 15.542713,11.600186 31.603513,21.226568 20.64752,12.37543 42.41225,22.91211 62.16406,36.77539 36.04918,22.69648 71.56888,46.70177 110.56836,64.16406 5.70349,2.69221 11.44483,5.30707 17.11133,8.07617 15.42875,7.53961 13.75597,7.46335 29.45899,14.45117 9.99878,4.44948 20.2682,8.41917 30.53906,12.18945 4.58751,1.68404 9.21492,3.25966 13.82226,4.88868 4.04834,1.46474 8.14081,2.80995 12.14454,4.39258 17.00003,6.7199 32.82668,16.00976 48.39648,25.49023 3.92561,1.91783 10.25952,4.99777 14.4668,7.09766 -1.27244,-0.007 -2.5461,-0.0396 -3.81446,0.0508 -15.23217,1.08501 -30.28776,3.64053 -45.05468,7.54297 -18.62714,5.44973 -22.73846,6.21799 -41.29688,13.51757 -27.55514,10.83829 -15.75534,7.10574 -42.14844,19.49024 -6.51651,3.05779 -30.96703,13.34 -37.58789,16.14453 -6.12184,3.35421 -12.09407,6.99653 -18.36523,10.0625 -11.80393,5.77088 -24.38991,9.83895 -36.21875,15.55859 -6.76193,3.26965 -13.33874,6.91309 -19.89258,10.58203 -18.83162,10.54228 -20.86113,12.34426 -38.88867,24.21094 -5.99972,4.48937 -12.17979,8.74455 -17.99805,13.4668 -5.47414,4.44295 -10.65317,9.24316 -15.85156,14.00586 -9.80299,8.98128 -17.24612,16.11523 -25.64453,26.37304 -3.39484,4.14647 -6.4258,8.57735 -9.54688,12.9336 -2.06422,2.8812 -4.04278,5.82375 -6.04296,8.75 2.35507,-15.57309 2.06338,-31.4689 4.52148,-47.04688 0.60038,-5.66986 1.40211,-11.32216 1.80078,-17.00976 0.502,-7.16169 0.64633,-14.3447 0.89844,-21.51953 0.6393,-18.19439 1.12921,-34.23186 0.73242,-52.52344 -0.49623,-22.87524 -1.78976,-37.32595 -3.39258,-60.25195 -3.33773,-26.81815 -4.18534,-33.63693 -7.47461,-60.03711 -1.15241,-9.24939 -2.42343,-18.48484 -3.45898,-27.74805 -0.97994,-8.7658 -1.79055,-17.54969 -2.58789,-26.33398 -0.78636,-8.66343 -1.103748,-17.37369 -2.164065,-26.00782 -1.034404,-8.4231 -2.743333,-16.74828 -4.115234,-25.12304 -1.2217,-6.87597 -2.489141,-13.74484 -3.664063,-20.62891 -0.831796,-4.873651 -1.459794,-9.783689 -2.357422,-14.644531 z" /> + <path + style="fill:#000000" + d="m 89.091797,77.679688 c -5.20187,3.266294 -0.404727,10.30491 -0.709843,15.16384 4.526161,26.307312 8.984239,52.510992 10.643902,79.182892 6.020464,61.00092 16.904904,121.71299 16.050314,183.16499 0.0707,32.01085 -1.76424,63.72639 -5.3803,95.45782 -0.19064,8.28992 -2.17452,16.74153 -1.73493,24.89765 4.12225,5.13687 8.40113,-2.5937 10.62304,-5.66993 36.78337,-50.60618 91.53232,-85.20998 148.31897,-109.71176 19.99215,-8.48238 38.77654,-19.53839 59.02156,-27.48768 26.17033,-12.1058 51.9659,-25.37614 79.81442,-33.34183 19.62906,-6.10616 39.76062,-10.17528 60.29232,-12.0349 6.61742,-3.02435 -0.93093,-8.03122 -4.87305,-9.05859 -23.30413,-13.34361 -46.59557,-27.23772 -72.46084,-35.1084 -34.61369,-11.66592 -66.83499,-29.11373 -99.85947,-44.71582 -51.92433,-26.01609 -98.58566,-61.51214 -149.74567,-89.10991 -16.79933,-9.13242 -32.03337,-20.744986 -47.791439,-31.442826 -0.702227,-0.391313 -1.45377,-0.230392 -2.208984,-0.185546 z" + id="path9" /> + </g> +</svg> diff --git a/chorechef_frontend/src/assets/icons/gear.svg b/chorechef_frontend/src/assets/icons/gear.svg new file mode 100644 index 0000000000000000000000000000000000000000..1c91b3a14216e9aa08ab5acf39ae01cac886a1aa --- /dev/null +++ b/chorechef_frontend/src/assets/icons/gear.svg @@ -0,0 +1,66 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + width="512" + height="512" + viewBox="0 0 512 512" + version="1.1" + id="svg1" + sodipodi:docname="gear.svg" + inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <sodipodi:namedview + id="namedview1" + pagecolor="#ffffff" + bordercolor="#999999" + borderopacity="1" + inkscape:showpageshadow="2" + inkscape:pageopacity="0" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1" + inkscape:document-units="px" + inkscape:zoom="1.1503906" + inkscape:cx="246.87267" + inkscape:cy="255.13073" + inkscape:window-width="1368" + inkscape:window-height="843" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="layer1" /> + <defs + id="defs1" /> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1"> + <circle + id="path1" + style="fill:#000000;stroke:#000000" + cx="2072.7852" + cy="207.6427" + r="2.8478267" /> + <circle + id="path4" + style="fill:#000000;stroke:#000000" + cx="1735.8708" + cy="-90.380722" + r="2.8478267" /> + <path + id="path6" + style="fill:#000000" + d="m -71.968724,44.200526 c 0.10678,0.0025 0.2139,0.0079 0.32031,0.01758 0.23486,0.02139 0.4312,0.06746 0.66211,0.113281 0.25881,0.05896 0.5108,0.136444 0.75977,0.22461 0.008,0.004 0.0157,0.0077 0.0234,0.01172 0.21093,0.141159 0.41991,0.285522 0.62695,0.431641 0.76867,2.738626 1.25985,4.700927 1.58594,6.8125 0.007,0.297067 0.0157,0.593558 0.0273,0.890625 0.015,0.505097 0.038,1.010969 0.0645,1.515625 0.0349,0.540312 0.0502,1.08155 0.0977,1.621094 0.0278,0.413725 0.0598,0.827484 0.0996,1.240234 0.0134,0.410002 0.0253,0.82025 0.0312,1.230469 0.008,0.327728 0.0366,0.654838 0.041,0.982422 0.0245,0.175436 0.0171,0.285218 0.10937,0.302734 3e-4,0.02083 0.002,0.04167 0.002,0.0625 0.031,0.292497 0.0505,0.585039 0.0645,0.878906 0.0133,0.306546 0.0234,0.613357 0.0391,0.919922 0.005,0.155752 0.0219,0.310772 0.041,0.464844 -0.0117,1.076553 -0.0407,2.154099 0.0625,3.22461 0.43494,4.510045 1.586,8.931409 2.02149,13.441406 0.5331,5.520915 0.56309,11.079704 0.88085,16.617181 0.40418,7.04322 0.85693,14.08321 1.28516,21.125 0.32731,8.60911 1.04569,17.21298 0.98242,25.82813 -0.0533,7.25913 -2.65105,46.802 -3.11133,53.65625 -4.49447,66.92986 0.61264,-9.60712 -4.56835,58.63476 -0.78366,10.322 -1.3783,20.65765 -2.06836,30.98633 -0.92891,10.12176 -1.86735,20.24263 -2.78711,30.36523 -0.88138,9.70005 -1.64031,19.41066 -2.61719,29.10157 -1.99373,19.77839 -3.65741,32.32055 -6.30469,51.75976 -0.95708,7.028 -1.78085,14.07702 -2.96484,21.07031 -0.93437,5.51892 -2.25727,10.96501 -3.38672,16.44727 -1.89626,9.99363 -3.12564,14.04167 -3.375,23.92188 -0.2379,9.4262 1.3315,18.79448 1.94726,28.16796 0.15865,2.41501 0.14015,4.83864 0.21094,7.25782 -0.11813,1.96906 0.052,3.97768 -0.35351,5.9082 -0.56513,2.69048 -2.6512,6.65825 -6.20508,6.5 -2.719636,-0.12111 -5.210956,-1.71024 -7.570316,-3.06836 -4.38133,-2.52205 -13.01734,-10.6612 -16.17773,-13.48047 -3.07815,-3.27348 -6.02962,-6.67062 -9.23438,-9.82031 -3.71423,-3.65045 -7.63623,-7.08324 -11.50781,-10.56641 -7.5234,-6.76863 -18.67988,-16.69057 -26.79492,-22.62695 -7.01174,-5.12928 -27.86904,-18.2894 -34.95703,-22.81836 -16.9684,-10.26397 -20.49321,-12.59268 -37.83789,-22.28906 -6.33578,-3.54196 -12.7966,-6.85706 -19.125,-10.41211 -9.24181,-5.19166 -22.64578,-13.6634 -32.51172,-18.01172 -6.49513,-2.86267 -13.29546,-4.97357 -19.94336,-7.46094 -10.80441,-5.09688 -25.72186,-12.36939 -36.86523,-16.67773 -7.18641,-2.77847 -14.55987,-5.04538 -21.83985,-7.56836 -7.32703,-2.81296 -14.68748,-5.53931 -21.98047,-8.43945 -15.80201,-6.284 -22.89994,-9.50162 -38.125,-16.11914 -8.36708,-4.63523 -17.77715,-7.17347 -26.1914,-11.72071 -1.49931,-0.81026 -2.51814,-2.3366 -3.99024,-3.19531 -2.0323,-1.18549 -4.30141,-1.90661 -6.43945,-2.88867 -5.0955,-2.3405 -4.75793,-2.25478 -9.88867,-4.95703 -0.67137,-1.11627 -1.83321,-2.05761 -2.01367,-3.34766 -0.71709,-5.12629 3.53902,-9.04049 6.66015,-12.30078 3.9962,-4.17438 7.1673,-7.17015 11.41406,-11.30274 11.5626,-9.41896 23.88817,-17.8272 37.11914,-24.72851 3.61782,-1.88706 7.3382,-3.57292 10.99805,-5.37695 3.95046,-1.9473 7.88928,-3.91804 11.83399,-5.87696 13.85228,-6.87939 27.59737,-13.97398 41.51562,-20.7207 5.92737,-2.87324 23.13726,-10.8227 28.9707,-14.12109 5.10466,-2.88634 9.93223,-6.23707 14.89844,-9.35547 23.61785,-16.82416 48.47588,-31.8934 73.86914,-45.875 11.6464,-6.41258 23.45552,-12.52827 35.17578,-18.80469 21.55947,-10.48441 41.57921,-23.69078 61.82222,-36.4375 15.63016,-9.842083 16.08347,-10.015342 31.7168,-19.447265 9.48522,-4.607574 17.711726,-11.544141 27.167966,-16.210938 2.63469,-1.300255 5.4269,-2.237362 8.20898,-3.199218 0.006,-0.0149 0.0119,-0.03404 0.0176,-0.04883 0.0409,-0.01192 0.0818,-0.02442 0.12305,-0.03516 0.29068,-0.07691 0.57807,-0.162751 0.86914,-0.238281 0.39072,-0.09743 0.78412,-0.189842 1.16992,-0.306641 0.44929,-0.115 0.90183,-0.224939 1.32031,-0.43164 0.3797,-0.191982 0.74414,-0.412686 1.09571,-0.652344 0.31464,-0.214747 0.61698,-0.446502 0.9375,-0.652344 0.0549,-0.0268 0.11255,-0.04546 0.16797,-0.07031 0.23882,-0.02127 0.47737,-0.04059 0.71679,-0.05469 0.31952,-0.0069 0.64058,-0.02518 0.96094,-0.01758 z m -14.54492,35.964844 c -3.65087,2.918638 -7.52891,5.990737 -9.33789,7.433593 -15.008226,10.760737 -15.542716,11.600177 -31.603516,21.226567 -20.64752,12.37543 -42.41225,22.91211 -62.16406,36.77539 -36.04918,22.69648 -71.56888,46.70177 -110.56836,64.16406 -5.70349,2.69221 -11.44483,5.30707 -17.11133,8.07617 -15.42875,7.53961 -13.75597,7.46335 -29.45899,14.45117 -9.99878,4.44948 -20.2682,8.41917 -30.53906,12.18945 -4.58751,1.68404 -9.21492,3.25966 -13.82226,4.88868 -4.04834,1.46474 -8.14081,2.80995 -12.14454,4.39258 -17.00003,6.7199 -32.82668,16.00976 -48.39648,25.49023 -3.92561,1.91783 -10.25952,4.99777 -14.4668,7.09766 1.27244,-0.007 2.5461,-0.0396 3.81446,0.0508 15.23217,1.08501 30.28776,3.64053 45.05468,7.54297 18.62714,5.44973 22.73846,6.21799 41.29688,13.51757 27.55514,10.83829 15.75534,7.10574 42.14844,19.49024 6.51651,3.05779 30.96703,13.34 37.58789,16.14453 6.12184,3.35421 12.09407,6.99653 18.36523,10.0625 11.80393,5.77088 24.38991,9.83895 36.21875,15.55859 6.76193,3.26965 13.33874,6.91309 19.89258,10.58203 18.83162,10.54228 20.86113,12.34426 38.88867,24.21094 5.99972,4.48937 12.17979,8.74455 17.99805,13.4668 5.47414,4.44295 10.65317,9.24316 15.85156,14.00586 9.80299,8.98128 17.24612,16.11523 25.64453,26.37304 3.39484,4.14647 6.4258,8.57735 9.54688,12.9336 2.06422,2.8812 4.04278,5.82375 6.04296,8.75 -2.35507,-15.57309 -2.06338,-31.4689 -4.52148,-47.04688 -0.60038,-5.66986 -1.40211,-11.32216 -1.80078,-17.00976 -0.502,-7.16169 -0.64633,-14.3447 -0.89844,-21.51953 -0.6393,-18.19439 -1.12921,-34.23186 -0.73242,-52.52344 0.49623,-22.87524 1.78976,-37.32595 3.39258,-60.25195 3.33773,-26.81815 4.18534,-33.63693 7.47461,-60.03711 1.15241,-9.24939 2.42343,-18.48484 3.45898,-27.74805 0.97994,-8.7658 1.790546,-17.54969 2.587886,-26.33398 0.78636,-8.66343 1.10375,-17.37369 2.16407,-26.00782 1.0344,-8.4231 2.74333,-16.74828 4.11523,-25.12304 1.2217,-6.87597 2.48914,-13.74484 3.66407,-20.62891 0.83179,-4.87365 1.45979,-9.783688 2.35742,-14.64453 z" /> + <path + style="fill:#000000" + d="m -86.930824,79.333339 c 5.20187,3.266294 0.40472,10.30491 0.70984,15.163831 -4.52616,26.30732 -8.98424,52.511 -10.6439,79.1829 -6.020466,61.00092 -16.904906,121.71299 -16.050316,183.16499 -0.0707,32.01085 1.76424,63.72639 5.3803,95.45782 0.19064,8.28992 2.17452,16.74153 1.73493,24.89765 -4.12225,5.13687 -8.40113,-2.5937 -10.62304,-5.66993 -36.78337,-50.60618 -91.53232,-85.20998 -148.31897,-109.71176 -19.99215,-8.48238 -38.77654,-19.53839 -59.02156,-27.48768 -26.17033,-12.1058 -51.9659,-25.37614 -79.81442,-33.34183 -19.62906,-6.10616 -39.76062,-10.17528 -60.29232,-12.0349 -6.61742,-3.02435 0.93093,-8.03122 4.87305,-9.05859 23.30413,-13.34361 46.59557,-27.23772 72.46084,-35.1084 34.61369,-11.66592 66.83499,-29.11373 99.85947,-44.71582 51.92433,-26.01609 98.58566,-61.51214 149.74567,-89.10991 16.79933,-9.13242 32.03337,-20.744985 47.791436,-31.442825 0.70223,-0.391313 1.45377,-0.230392 2.20899,-0.185546 z" + id="path9" /> + <path + id="path20" + style="fill:#000000" + d="m 241.02344,7.0410156 a 249.82173,248.80815 0 0 0 -0.46485,0.03125 c 0.0985,0.1264188 0.19852,0.2527137 0.30469,0.3730469 0.0479,-0.1283059 0.11049,-0.2741381 0.16016,-0.4042969 z m -24.39258,2.8691406 a 249.82173,248.80815 0 0 0 -19.99024,4.2519528 c -0.96614,0.53266 -1.92275,0.723756 -2.79296,0.595703 a 249.82173,248.80815 0 0 0 -30.04493,9.449219 c -0.94209,0.590429 -1.85273,1.227912 -2.65234,2.025391 -1.45697,1.19756 -2.7081,2.588906 -3.8457,4.09375 -0.86953,1.030846 -1.63463,2.142823 -2.42969,3.228516 -0.78508,2.818718 -1.334,5.684079 -1.10547,8.664062 0.15755,2.753247 0.39339,5.502375 0.70313,8.242188 0.19567,0.619972 0.38732,1.23995 0.70703,1.822265 0.58848,1.15059 0.92279,2.413737 0.99609,3.689453 0.23913,1.541191 0.13554,3.068345 -0.28906,4.570313 -0.032,0.127658 -0.0813,0.251893 -0.11719,0.378906 0.0992,2.636221 -0.19542,5.243401 -1.51758,7.667969 -0.36587,0.57133 -0.68513,1.176182 -1.09765,1.714844 -1.32755,1.733412 -3.07797,3.01133 -4.90821,4.18164 -0.36518,0.277484 -0.77705,0.506902 -1.18945,0.734375 -0.28636,0.172929 -0.56488,0.355367 -0.85156,0.525391 -0.038,0.02713 -0.0822,0.04797 -0.11914,0.07617 -0.21568,0.158815 -0.44526,0.292491 -0.67969,0.416015 -0.20652,0.122602 -0.41263,0.257857 -0.61719,0.38086 -0.51417,0.281043 -1.01379,0.588614 -1.52734,0.871093 -0.70904,0.519305 -1.60752,0.820818 -2.22461,1.486328 -1.02,0.502205 -2.04665,0.992526 -2.92188,1.732422 -1.39886,0.745264 -2.68456,1.641421 -4.11328,2.332032 -0.49678,0.203898 -0.9843,0.428282 -1.46875,0.658203 -3.60034,2.211687 -7.19108,4.440614 -10.66211,6.853515 -4.07835,2.603974 -8.22105,5.192666 -12.96093,6.40625 -3.29752,0.842253 -6.57962,1.420408 -9.919926,0.390625 -3.788114,-1.406073 -7.102436,-3.640677 -10.148437,-6.289062 -0.95592,-0.867101 -1.907311,-1.74279 -2.855469,-2.621094 -0.544771,-0.153337 -1.079655,-0.351722 -1.564453,-0.617187 -0.576134,-0.09642 -1.150714,-0.341598 -1.6875,-0.685547 -2.523567,0.278641 -4.9174,1.045516 -7.335937,1.78125 -2.703811,0.888863 -5.253011,2.224506 -7.722657,3.666015 A 249.82173,248.80815 0 0 0 27.380859,155.84766 c -0.251597,2.0346 -0.333337,4.08629 -0.384765,6.13476 0.107287,1.93203 0.507526,3.83632 1.138672,5.66211 0.473622,2.00194 1.258555,3.91444 2.013672,5.82813 1.69696,2.45473 3.455145,4.86494 5.365234,7.17187 2.712,3.46374 5.338653,6.99252 7.884766,10.58008 2.332648,3.48458 4.619305,7.1103 5.320312,11.32031 0.553365,3.71672 0.661237,7.41074 0.002,11.13086 -0.714173,3.83002 -1.279518,7.68574 -2.082031,11.5 -0.673469,3.70155 -1.338741,7.40519 -2.00586,11.10742 -0.556595,2.65566 -1.133708,5.30309 -1.861328,7.91797 -0.608243,2.26865 -1.31097,4.54454 -2.410156,6.62695 -1.151307,2.14054 -2.557172,4.11946 -3.980469,6.08594 -1.423387,1.7531 -2.780459,3.57059 -4.466797,5.08985 -1.870631,1.69934 -4.038852,3.02614 -6.05664,4.53906 -2.680878,1.6593 -5.373691,3.29784 -8.214844,4.67578 -1.886629,1.0002 -3.735754,2.08386 -5.347656,3.49609 -1.124671,1.27746 -2.3841471,2.43026 -3.1250001,3.9961 -0.5898081,1.34479 -1.2380992,2.6537 -1.5117188,4.08789 A 249.82173,248.80815 0 0 0 30.275391,359.5332 c 1.685675,1.87279 3.360761,3.75563 5.082031,5.59766 0.258238,0.27115 0.569316,0.49212 0.84375,0.75 1.439612,0.473 2.925226,0.76724 4.402344,1.09766 0.714199,-0.0469 1.411799,0.24442 2.144531,0.0488 0.792331,-0.0424 1.563952,-0.25432 2.345703,-0.23632 1.287669,-0.28865 2.542026,-0.7103 3.828125,-1.00196 1.863281,-0.37602 3.682316,-0.8946 5.556641,-1.20508 1.313688,-0.16743 2.618858,-0.42751 3.939453,-0.51367 2.654645,-0.9494 5.304883,-1.91244 7.912109,-2.98437 2.315852,-0.78381 4.603846,-1.7292 7.039063,-2.07032 1.376833,-0.19932 2.753654,-0.34156 4.132812,-0.39062 1.379191,-0.0491 2.762036,-0.004 4.148438,0.17383 2.674412,0.3505 5.351183,0.786 7.929687,1.59765 2.554665,0.8819 5.09614,1.80821 7.484375,3.0879 2.669099,1.16284 5.302697,2.55208 7.197267,4.82617 1.32071,1.81877 2.3802,3.76285 3.22461,5.84765 1.09162,1.99694 2.196,3.97233 3.54492,5.81055 1.62279,2.23029 3.31573,4.39325 5.35156,6.26953 2.56825,2.329 5.21969,4.55063 7.89649,6.75195 2.55277,2.33468 5.03558,4.75015 7.18945,7.4668 2.12241,2.37246 4.23189,4.75653 6.3457,7.13672 1.88271,2.34966 3.7476,4.74907 4.95703,7.5293 1.21855,2.39896 1.83415,5.04653 2.00977,7.73047 -0.0947,1.75756 -0.2736,3.49402 -1.01172,5.11718 -0.14665,0.48342 -0.31772,0.95846 -0.4707,1.43946 -0.002,0.0209 -0.002,0.0416 -0.004,0.0625 -0.28118,1.36241 -0.33712,2.75627 -0.51172,4.13476 -0.15948,1.71912 -0.36302,3.46672 -0.79297,5.13281 -0.4813,1.6262 -0.91515,3.26174 -1.41406,4.88282 -0.3324,1.04405 -0.75425,2.05899 -0.91797,3.15039 -0.10224,1.41235 -0.59975,2.82181 -0.59375,4.26367 -0.35351,1.5424 -0.69,3.10713 -0.7539,4.6875 -0.1792,1.33469 -0.32725,2.65953 -0.37305,4 0.11387,0.7392 0.14619,1.48559 0.16406,2.23242 0.97829,1.80113 1.99685,3.58103 3.03711,5.33789 1.64037,2.67817 3.19924,5.41034 5.27539,7.79102 1.18844,1.14364 2.37508,2.27699 3.64453,3.31836 a 249.82173,248.80815 0 0 0 53.76953,18.92773 c 0.23676,-0.0401 0.47064,-0.0939 0.70899,-0.12695 2.30546,-0.36078 4.59378,-0.75726 6.93164,-0.81836 1.313,-0.16468 2.62962,-0.10756 3.9375,-0.34375 1.74446,-0.26499 3.50336,-0.21841 5.23633,-0.56641 0.96529,0.0165 1.72832,-0.23532 2.66406,-0.32812 0.84585,-0.0839 1.65738,0.10404 2.4375,-0.39844 1.65863,-0.16113 3.25889,-0.80955 4.89844,-1.10547 1.39196,-0.35053 2.76676,-0.65358 4.16797,-0.90234 1.42597,-0.31299 2.78063,-0.7489 4.20117,-1.04102 1.0011,-0.27451 2.00131,-0.50369 2.98633,-0.82422 0.50269,-0.39587 1.23556,-0.49637 1.73047,-0.90625 0.36358,-0.51282 -0.19813,0.23904 0.58789,-0.55468 0.70658,-0.71363 1.3687,-1.4884 2.04492,-2.23438 0.94992,-0.88736 1.71755,-1.95387 2.68359,-2.82812 0.98444,-1.07198 2.0822,-1.99441 3.17774,-2.94727 0.87364,-0.96568 1.8945,-1.78661 2.68554,-2.83008 0.84291,-1.05538 1.7244,-2.07861 2.48438,-3.19531 0.5902,-1.08366 1.36201,-2.02468 2.15625,-2.95313 0.54808,-1.02284 1.13501,-2.02129 1.58789,-3.10351 1.55306,-3.4563 3.13092,-6.95729 5.60547,-9.87305 2.37102,-2.5019 5.09369,-4.5512 8.45508,-5.50195 2.67242,-0.76759 5.37407,-1.3299 8.12109,-1.77149 2.99691,-0.39335 5.96171,-1.0339 8.96289,-1.40234 2.4527,-0.46938 4.90482,-0.98609 7.30078,-1.69141 2.77877,-0.87568 5.52694,-1.83159 8.26758,-2.82031 2.67368,-0.93334 5.43185,-1.76019 8.26562,-1.99219 2.66099,-0.0238 5.28925,0.29138 7.84766,1.06055 2.47435,0.73645 4.83314,1.79771 7.05469,3.11719 2.32294,1.3637 4.48538,2.91899 6.45117,4.77148 1.98777,1.76713 3.96753,3.54843 5.71094,5.56446 0.71549,0.84717 1.33091,1.76372 1.94726,2.67968 0.017,0.0181 0.0385,0.0319 0.0547,0.0508 0.18352,0.21379 0.33053,0.46016 0.48828,0.69727 0.0366,0.0577 0.081,0.11003 0.11719,0.16797 0.34372,0.5309 0.68097,1.06953 1.11523,1.52539 0.40923,0.80568 0.98388,1.51664 1.56641,2.20117 0.72125,0.91981 1.1954,1.90078 1.98047,2.77735 0.34762,0.63803 0.77226,1.21133 1.1875,1.80468 0.48046,0.56603 1.05401,1.02711 1.42773,1.67383 0.65831,0.59116 1.26586,1.20318 1.88086,1.83399 0.63743,0.62266 1.33058,1.18145 2.01172,1.72656 0.54528,0.31674 1.05464,0.72133 1.58789,1.0625 0.37667,0.19782 1.12613,0.46966 1.30078,0.72656 0.32012,0.0208 0.74647,0.17363 1.125,0.20313 0.7446,-0.10537 1.50026,-0.0541 2.25391,-0.14649 1.00933,-0.16836 2.03142,-0.25605 3.0293,-0.49805 a 249.82173,248.80815 0 0 0 57.70117,-40.07031 c 1.4782,-2.89987 3.18607,-5.67102 4.9414,-8.41406 2.04663,-3.33292 3.79948,-6.78829 4.73633,-10.61133 0.40724,-2.04635 0.88338,-4.08937 0.85938,-6.18555 -0.0143,-1.66003 0.0827,-3.30289 -0.19922,-4.95703 -0.26089,-1.33292 -0.43666,-2.67744 -0.76953,-3.99414 -0.27633,-1.06266 -0.44884,-2.1444 -0.71875,-3.20508 -0.004,-0.0189 -0.0343,-0.1851 -0.0449,-0.23437 -0.14334,-0.27614 -0.33041,-0.52635 -0.44922,-0.81641 -2.41209,-3.1294 -4.61335,-6.42683 -5.87696,-10.20508 -1.07275,-3.31757 -2.10744,-6.66292 -2.5957,-10.10937 -0.22963,-1.01597 -0.35438,-2.0542 -0.35156,-3.11523 0.0149,-0.49735 0.074,-0.97887 0.15625,-1.45313 0.0787,-2.95798 0.39619,-5.84197 2.09961,-8.40039 1.79549,-2.90517 3.78341,-5.66053 5.77343,-8.43359 2.25905,-3.18328 4.60973,-6.30693 6.70313,-9.60352 2.35132,-3.8538 4.31431,-7.89494 5.92383,-12.11719 1.74901,-4.47756 3.57699,-8.93614 5.94726,-13.1289 2.24452,-4.24715 4.46591,-8.52116 6.19141,-13.01172 1.6535,-3.72876 3.0513,-7.79219 6.24219,-10.51367 2.81636,-1.81476 5.95004,-2.55809 9.29687,-2.64649 3.56848,-0.24524 7.1404,-0.40133 10.70313,-0.72265 1.61896,-0.17267 3.24132,-0.29737 4.86328,-0.42579 0.24438,-0.0511 0.48697,-0.11427 0.7207,-0.22265 1.01726,-0.19925 2.00055,-0.49177 3.04297,-0.57227 0.50647,-0.0922 0.94335,-0.44536 1.48438,-0.44336 0.55952,-0.21628 1.15344,-0.4287 1.72851,-0.4707 0.48992,-0.18791 0.92479,-0.37302 1.41016,-0.47852 0.76982,-0.2853 1.51696,-0.56335 2.22265,-0.99218 0.56621,-0.25133 1.18456,-0.34904 1.70703,-0.65821 0.22801,-0.14408 0.44978,-0.32876 0.55469,-0.25586 -0.20261,-0.0126 -0.12334,0.22429 0.13672,-0.0879 0.25543,-0.49334 0.44233,-1.04194 0.67774,-1.55273 0.1565,-0.31218 0.52191,-0.70962 0.63476,-0.95899 0.13746,-0.30357 0.0745,-0.62182 0.39649,-0.90039 0.38452,-0.75103 0.65058,-1.57043 1.08593,-2.2832 a 249.82173,248.80815 0 0 0 2.22657,-30.20117 249.82173,248.80815 0 0 0 -6.83008,-54.10156 c -0.0816,-0.0841 -0.15838,-0.17206 -0.22656,-0.26758 -0.32922,-0.45999 -0.23283,-1.82252 -0.49219,-2.37891 -0.34822,-1.22825 -0.46117,-2.5057 -0.8711,-3.71679 -0.0317,-0.8735 -0.24961,-1.81419 -0.63086,-2.5918 -0.14463,-0.35264 -0.30312,-0.78248 -0.40429,-1.06055 -0.50227,-0.58604 -0.9093,-1.24919 -1.41602,-1.83398 -0.16036,-0.2104 -0.31504,-0.42846 -0.4707,-0.64453 -0.44766,-0.48909 -0.92178,-0.95662 -1.25586,-1.53321 -0.23836,-0.1927 -0.41821,-0.47053 -0.63672,-0.69336 -0.14371,-0.13793 -0.27385,-0.2725 -0.36914,-0.39648 -0.003,-0.006 -0.007,-0.0114 -0.01,-0.0176 -0.28497,-0.31905 -0.59185,-0.60568 -0.86328,-0.94141 -0.17174,-0.13013 -0.34723,-0.2588 -0.50976,-0.39257 -2.65426,-0.91507 -5.32474,-1.77705 -8.06446,-2.41211 -2.84018,-0.712 -5.67947,-1.43737 -8.58984,-1.8125 -3.66418,-0.60066 -7.31138,-1.30021 -10.96484,-1.95899 -3.47044,-0.67001 -6.92476,-1.42037 -10.41602,-1.98242 -3.47863,-0.62783 -6.9971,-1.10563 -10.38867,-2.12109 -3.06667,-0.91978 -6.17531,-1.88908 -8.62891,-4.03906 -2.10814,-2.28124 -3.52711,-4.80144 -3.7539,-7.9629 -0.23804,-2.44686 -0.21205,-4.90763 -0.58203,-7.34179 -0.49456,-2.88342 -1.27721,-5.70506 -2.06055,-8.52149 -0.67887,-2.6633 -1.56396,-5.27828 -2.61914,-7.8164 -1.08825,-2.87157 -2.40461,-5.65741 -3.8711,-8.35547 -1.76724,-2.83566 -3.64656,-5.56972 -5.91211,-8.04297 -2.58724,-3.03812 -5.08184,-6.1838 -7.24023,-9.54297 -1.36095,-2.42539 -2.62867,-4.89586 -3.83008,-7.4043 -0.78957,-2.14238 -1.28136,-4.34366 -1.00195,-6.642574 0.26986,-2.333352 0.94803,-4.540859 1.89453,-6.691407 1.09797,-2.713517 2.65386,-5.212918 4.00195,-7.80664 1.28138,-2.368286 2.72967,-4.654003 3.78516,-7.134766 0.66093,-1.812226 1.30175,-3.616966 1.44531,-5.556641 0.21625,-1.744709 0.41036,-3.550674 0.16407,-5.296874 -0.20395,-1.439463 -0.66524,-2.825542 -1.36719,-4.097657 A 249.82173,248.80815 0 0 0 361.48828,29.919922 c -0.582,-0.106572 -1.16192,-0.228959 -1.75586,-0.275391 -0.54683,-0.0906 -1.08468,-0.07737 -1.62695,-0.07617 -1.50285,0.175781 -2.99638,0.459341 -4.47852,0.744141 -0.9523,0.162411 -2.06911,0.229857 -2.98242,0.535156 -0.26737,0.08938 -0.48683,0.290869 -0.75195,0.386719 -0.2584,0.09342 -0.53625,0.117191 -0.80469,0.175781 -1.53172,0.602302 -3.12217,1.031591 -4.5332,1.927735 -1.98175,1.135885 -3.99212,2.263366 -5.82617,3.621093 -2.07406,1.00443 -3.88512,2.395013 -5.74414,3.744141 -1.42873,0.845402 -2.61215,1.950692 -3.97461,2.873047 -0.69763,0.452803 -1.36007,0.947248 -2.08594,1.345703 -0.72742,0.664544 -1.6604,1.044508 -2.31055,1.818359 -1.02388,0.962642 -2.20009,1.843859 -3.38672,2.59375 -1.06643,0.758252 -2.14394,1.496558 -3.17968,2.294922 -0.86532,0.498539 -1.44598,1.35039 -2.33985,1.810547 -1.28204,1.021391 -2.6071,1.955199 -4.24805,2.337891 -0.78687,0.05246 -1.55356,0.281756 -2.35937,0.285156 -0.81775,-0.305772 -1.86207,0.04397 -2.67578,-0.363281 -0.52968,-0.09382 -1.07805,0.0109 -1.61328,-0.04297 -3.32627,0.0099 -6.65022,-0.492706 -9.92774,-1.019531 -1.30498,-0.223856 -2.60539,-0.475571 -3.90234,-0.744141 -1.29807,-0.124845 -2.59232,-0.2821 -3.88867,-0.396484 -3.54272,-0.356488 -7.13488,-0.639112 -10.58203,-1.558594 -2.7947,-0.807968 -5.42479,-2.036059 -8.15235,-3.035156 -3.09074,-1.207908 -6.31118,-2.014874 -9.46289,-3.046875 -3.30265,-1.131461 -6.56223,-2.528182 -9.14844,-4.94336 -1.04712,-1.002993 -2.00377,-2.088437 -2.91797,-3.210937 -0.85261,-0.613971 -1.60332,-1.412801 -2.2539,-2.19336 -0.77397,-0.684165 -1.38943,-1.540579 -1.91016,-2.429687 -0.63958,-0.763088 -1.16106,-1.634474 -1.69531,-2.472656 -0.46201,-0.92709 -1.20253,-1.711476 -1.68945,-2.63086 -0.29261,-0.48242 -0.34504,-0.606272 -0.47071,-0.732421 -0.41657,-0.627226 -0.99865,-1.129962 -1.47851,-1.705079 -0.38054,-0.409438 -0.62091,-0.83469 -1,-1.283203 -0.39109,-0.508696 -0.7486,-1.029931 -1.13672,-1.539062 -0.34745,-0.444429 -0.62944,-1.012887 -1.12695,-1.310547 -0.39121,-0.420283 -0.73527,-0.867831 -1.2168,-1.210938 -0.26023,-0.36324 -0.99632,-0.669865 -1.29297,-1.091797 -0.82103,-0.630288 -1.5795,-1.312363 -2.28125,-2.089843 -0.62742,-0.598118 -1.07245,-1.313332 -1.56445,-2.00586 -0.24778,-0.414793 -1.04189,-1.342722 -1.53711,-1.875 -0.13882,-0.149837 0.10661,0.01672 -0.41992,-0.466797 -0.10538,-0.0094 -0.63051,-0.418747 -1.08008,-0.826171 -0.37487,-0.145896 -0.85861,-0.318125 -1.19141,-0.498047 -0.87935,-0.466058 -1.85012,-0.750916 -2.67383,-1.322266 -0.92722,0.06082 -1.86565,0.05365 -2.77734,0.03711 -0.46234,-0.077765 -0.93193,-0.1069155 -1.40039,-0.1445318 z m 51.86328,6.3691408 c 0.1035,0.07735 0.20504,0.157101 0.30859,0.234375 0.0128,-0.0491 0.0243,-0.113594 0.0371,-0.16211 -0.11521,-0.0243 -0.23043,-0.04828 -0.3457,-0.07227 z M 245.51953,148.15234 c 0.42971,0.0131 0.84562,0.16073 1.27344,0.20313 1.27141,0.12602 2.57131,0.002 3.82031,0.3418 2.15858,0.0694 4.29468,0.49286 6.46289,0.44726 2.84682,0.0637 5.6263,0.76694 8.45899,0.9668 1.1584,0.32588 2.34223,0.52747 3.52734,0.72851 0.23633,-0.0433 0.31039,-0.0769 0.5625,-0.12109 0.98531,-0.17259 1.91951,0.32019 2.85156,0.8125 0.18703,0.0495 0.37478,0.0965 0.56055,0.15234 2.40934,0.60734 4.72358,1.53645 7.0293,2.45508 0.77235,0.39167 1.90561,0.93374 2.59375,1.42969 0.25448,0.18341 0.60258,0.47649 0.97461,0.82617 4.88744,2.31742 9.69513,4.71137 14.43164,7.35156 1.46228,0.81516 2.97738,1.53983 4.40039,2.42188 1.43627,0.89027 2.77728,1.92592 4.16601,2.88867 3.72905,3.02181 7.51139,6.00441 11.01172,9.29492 2.5327,2.38093 4.34584,4.3693 6.67969,6.96289 1.11228,1.2361 2.20083,2.49317 3.30078,3.74024 2.97053,3.66959 3.6062,4.33218 6.32617,8.18359 3.85391,5.45714 7.02203,11.33583 10.22071,17.18945 4.444,9.27675 8.07815,18.88835 9.08398,29.20704 0.13454,1.29999 0.18877,2.61663 0.31641,3.92187 0.79869,3.50943 1.55297,7.03095 2.16992,10.58008 0.88519,4.18785 0.75986,8.40469 0.58984,12.64844 -0.34524,4.73672 -1.24537,9.41953 -2.00195,14.10546 -0.58583,4.26441 -1.72059,8.3859 -2.78125,12.54297 -1.10826,4.22331 -2.92012,8.15589 -5.28321,11.81055 -2.74915,4.12083 -6.30399,7.62956 -9.66992,11.24219 -0.58939,0.54085 -1.20006,1.06127 -1.76953,1.62305 -0.64958,0.64078 -1.23209,1.34677 -1.88672,1.98242 -2.59656,2.52134 -5.5605,4.69988 -8.40625,6.92578 -4.27753,3.34693 -8.91386,6.13105 -13.60742,8.83789 -5.57337,3.08486 -11.43979,5.55627 -17.36523,7.86914 -6.1857,2.39493 -12.58876,4.12241 -19,5.78711 -6.27284,1.39802 -12.63684,2.35025 -19.04688,2.79101 -6.17857,0.46617 -12.37946,0.14985 -18.52734,-0.53515 -6.45214,-0.40196 -12.76583,-2.05416 -18.81641,-4.26953 -2.81199,-1.20725 -5.77645,-2.27115 -8.44336,-3.79297 -2.80842,-1.60257 -5.65796,-3.84239 -8.30664,-5.72656 -0.72491,-0.53168 -1.36293,-1.14848 -2.03711,-1.73047 -2.35274,-1.18777 -4.45024,-2.75036 -6.56836,-4.3086 -1.96476,-1.66779 -4.02131,-3.19015 -6.02929,-4.80273 -2.78422,-1.90504 -5.47668,-4.0142 -8.04493,-6.21484 -2.67149,-2.14694 -5.04316,-4.61853 -7.20507,-7.26954 -2.59078,-3.14161 -4.8534,-6.52296 -7.00586,-9.97461 -2.45873,-3.90438 -4.59641,-7.99883 -6.68946,-12.10742 -2.03355,-4.1348 -3.77107,-8.43935 -5.13672,-12.83984 -1.87699,-5.79372 -2.84663,-11.83073 -3.5664,-17.86524 -0.84904,-6.7597 -1.08447,-13.62373 -0.76953,-20.42773 0.26221,-7.80434 1.37493,-15.52854 2.91015,-23.17383 1.894,-8.15406 4.71517,-16.03784 8.47657,-23.52148 0.91633,-1.8231 1.95443,-3.58184 2.93164,-5.37305 5.18441,-9.36131 11.86437,-17.70746 18.79297,-25.80859 3.09113,-2.97252 6.27937,-5.90119 9.82421,-8.33594 3.12333,-2.14523 6.51658,-3.7895 9.92579,-5.41211 3.27734,-1.25232 6.59421,-2.50143 10.06054,-3.13477 1.14158,-0.20858 2.30132,-0.29204 3.45313,-0.43359 1.13718,-0.13975 2.26819,-0.34566 3.41211,-0.41016 1.16994,-0.0659 2.34384,0.0125 3.51562,0.0195 4.47955,0.0303 2.76093,-0.10911 7.06446,0.40234 0.16468,0.0196 0.33073,0.0325 0.49609,0.0488 3.24357,-0.51062 6.26206,-0.94211 9.54687,-0.89844 0.3845,0.005 0.77075,-0.009 1.15625,-0.008 0.3855,9.2e-4 0.77076,0.0149 1.15039,0.0762 0.015,0.002 0.0819,0.0277 0.0996,0.0312 0.28588,-0.031 0.57045,-0.0653 0.85938,-0.0859 0.23936,-0.0203 3.15518,-0.27758 3.47656,-0.26758 z M 17.470703,194.38086 c -0.0035,0.0466 -0.01622,0.0921 -0.01953,0.13867 0.0083,-0.02 0.01513,-0.0403 0.02344,-0.0606 -0.0015,-0.026 -0.0024,-0.0521 -0.0039,-0.0781 z m 6.927735,44.48828 c -0.03469,0.13911 -0.06615,0.27905 -0.101563,0.41797 0.07525,-0.13792 0.145097,-0.27933 0.224609,-0.41406 -0.0411,-0.002 -0.08195,-0.002 -0.123046,-0.004 z M 285.4043,305.86328 c 0.16734,0.28515 0.33458,0.49334 0.48242,0.53125 -0.15876,-0.20683 -0.3203,-0.37183 -0.48242,-0.53125 z m 36.46875,143.10352 c 0.70106,0.20994 1.3928,0.45197 2.07422,0.70703 0.4567,0.1269 0.91314,0.24753 1.37109,0.36523 -0.84352,-0.32272 -1.69163,-0.63441 -2.55274,-0.92578 -0.29298,-0.0785 -0.59766,-0.0771 -0.89257,-0.14648 z m -14.02735,24.72461 c -0.0601,0.0326 -0.12195,0.0683 -0.17578,0.10937 0.0579,-0.005 0.1159,-0.0103 0.17383,-0.0156 10e-4,-0.0326 2.9e-4,-0.0618 0.002,-0.0937 z" /> + </g> +</svg> diff --git a/chorechef_frontend/src/assets/main.css b/chorechef_frontend/src/assets/main.css new file mode 100644 index 0000000000000000000000000000000000000000..0cb34ed1082cf088eeadddacb9f38ad028363a47 --- /dev/null +++ b/chorechef_frontend/src/assets/main.css @@ -0,0 +1,12 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +.indie-flower-regular { + font-family: "Indie Flower", cursive; + font-weight: 400; +} +.indie-flower-bold { + font-family: "Indie Flower", cursive; + font-weight: 800; +} diff --git a/chorechef_frontend/src/components/Chores.vue b/chorechef_frontend/src/components/Chores.vue new file mode 100644 index 0000000000000000000000000000000000000000..0b5876ac96f37ec2fb66371972da55c7073e9fc8 --- /dev/null +++ b/chorechef_frontend/src/components/Chores.vue @@ -0,0 +1,557 @@ +<script setup lang="ts"> +import { add, format, compareAsc } from "date-fns"; +import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; +import { + faCirclePlus, + faCheck, + faTrash, + faPenToSquare, + faCaretUp, + faCaretDown, + faTimes, + faBackward, + faFloppyDisk, + faCircleCheck, + faTriangleExclamation, +} from "@fortawesome/free-solid-svg-icons"; +import { faCircle } from "@fortawesome/free-regular-svg-icons"; +import AirDatepicker from "air-datepicker"; +import localeDe from "air-datepicker/locale/de"; +import "air-datepicker/air-datepicker.css"; +</script> +<template> + <div + class="flex flex-col gap-2 m-2 rounded-xl shadow-lg bg-secondary-400 grow" + > + <h2 + class="text-xl font-bold bg-secondary-300 rounded-xl shadow-lg m-4 px-4 py-2" + > + Aufgaben + </h2> + <div + id="chores" + v-for="chore in chores" + class="flex flex-row items-center p-1 rounded-xl shadow-lg mx-4 bg-secondary-200" + :class="{ + 'text-red-600': isOverdue(new Date(chore.chore_date)) && onDashboard, + 'text-gray-600 italic line-through': chore.chore_done && onDashboard, + }" + > + <div + class="hover:cursor-pointer w-6 h-6 mx-4 flex items-center justify-center rounded-full shadow-lg bg-secondary-100 hover:scale-110 hover:drop-shadow-lg border-black border transition" + v-if="onDashboard" + @click="forwardChore(chore)" + > + <div class="opacity-0 hover:opacity-100 transition-opacity"> + <FontAwesomeIcon :icon="faCheck" /> + </div> + </div> + + <!-- Chore Name --> + <div v-if="editingChore === chore" class="w-3/12"> + <input + v-focus + v-on:keyup.enter="saveChore(chore)" + type="text" + v-model="chore.chore_name" + placeholder="Aufgabe" + class="rounded-xl px-4 shadow-lg py-0 bg-secondary-50 border-none focus:ring-2 focus:ring-secondary-600 w-4/5 indie-flower-regular text-lg" + /> + </div> + <div v-else class="w-3/12"> + <div + class="rounded-xl px-4 shadow-lg py-0 bg-secondary-100 border-none focus:ring-2 focus:ring-secondary-600 w-4/5 indie-flower-regular text-lg" + > + <div> + {{ chore.chore_name }} + </div> + </div> + </div> + + <!-- Chore Date --> + <div v-if="editingChore === chore" class="w-3/12"> + am + <input + id="chore-date-picker" + v-on:keyup.enter="saveChore(chore)" + type="text" + v-model="editingChore.chore_date" + class="rounded-xl mx-1 px-2 shadow-lg py-0 bg-secondary-50 border-none focus:ring-2 focus:ring-secondary-600 w-1/2" + /> + </div> + <div + v-else + class="flex" + :class="{ 'w-2/12': '!onDashboard', 'w-3/12': 'onDashboard' }" + > + am + <div + class="rounded-xl mx-2 px-2 shadow-lg py-0 bg-secondary-100 border-none focus:ring-2 focus:ring-secondary-600 w-1/2" + > + {{ formatDate(chore.chore_date) }} + </div> + </div> + + <!-- Chore Frequency --> + <div v-if="editingChore === chore" class="w-3/12 gap-1 flex"> + alle + <input + v-on:keyup.enter="saveChore(chore)" + type="number" + v-model="chore.chore_frequency" + class="rounded-xl shadow-lg py-0 bg-secondary-50 border-none focus:ring-2 focus:ring-secondary-600 w-1/6" + /> + <select + v-on:keyup.enter="saveChore(chore)" + v-model="chore.chore_frequency_unit" + class="rounded-xl shadow-lg py-0 bg-secondary-50 border-none focus:ring-2 focus:ring-secondary-600 w-3/6" + > + <option value="Tage">Tage</option> + <option value="Wochen">Wochen</option> + <option value="Monate">Monate</option> + </select> + </div> + <div v-else class="flex gap-1 w-3/12"> + alle + <div + class="rounded-xl px-3 shadow-lg py-0 bg-secondary-100 border-none focus:ring-2 focus:ring-secondary-600 w-1/6" + > + {{ chore.chore_frequency }} + </div> + <div + class="rounded-xl px-3 shadow-lg py-0 bg-secondary-100 border-none focus:ring-2 focus:ring-secondary-600 w-3/6" + > + {{ chore.chore_frequency_unit }} + </div> + </div> + + <!-- Chore User --> + <div v-if="editingChore === chore" class="w-2/12"> + <select + v-on:keyup.enter="updateChore(chore)" + v-model="chore.chore_user" + class="rounded-xl px-3 shadow-lg py-0 bg-secondary-50 border-none focus:ring-2 focus:ring-secondary-600 w-7/12" + > + <option + v-for="user in users" + :value="user.user_id" + :key="user.user_id" + > + {{ user.username }} + </option> + </select> + </div> + <div v-else class="w-2/12"> + <div + class="rounded-xl px-3 shadow-lg py-0 bg-secondary-100 border-none focus:ring-2 focus:ring-secondary-600 w-7/12" + > + {{ getUserName(chore.chore_user) }} + </div> + </div> + + <!-- Empty Space --> + <div class="flex grow"></div> + + <!-- Chore Actions --> + <div + id="chore-actions" + class="flex flex-row gap-2 pr-4" + v-if="!onDashboard" + > + <div + class="rounded-xl shadow-lg bg-secondary-100 hover:scale-110 hover:drop-shadow-lg hover:cursor-pointer px-1" + @click="saveChore(chore)" + v-if="editingChore === chore" + > + <FontAwesomeIcon :icon="faCheck" class="hover:cursor-pointer" /> + </div> + <div + class="rounded-xl shadow-lg bg-secondary-100 hover:scale-110 hover:drop-shadow-lg hover:cursor-pointer px-1" + @click="cancelEditChore(chore)" + v-if="editingChore === chore" + > + <FontAwesomeIcon :icon="faTimes" class="hover:cursor-pointer" /> + </div> + <div + class="rounded-xl shadow-lg bg-secondary-100 hover:scale-110 hover:drop-shadow-lg hover:cursor-pointer px-1" + @click="backwardChore(chore)" + v-if="!editingChore && !chore.chore_done" + > + <FontAwesomeIcon :icon="faBackward" class="hover:cursor-pointer" /> + </div> + <div + class="rounded-xl shadow-lg bg-secondary-100 hover:scale-110 hover:drop-shadow-lg hover:cursor-pointer px-1" + @click="editChore(chore)" + v-if="editingChore !== chore" + > + <FontAwesomeIcon :icon="faPenToSquare" class="hover:cursor-pointer" /> + </div> + <div + class="rounded-xl shadow-lg bg-secondary-100 hover:scale-110 hover:drop-shadow-lg hover:cursor-pointer px-1" + > + <FontAwesomeIcon + :icon="faTrash" + class="hover:cursor-pointer" + @click="deleteChore(chore)" + /> + </div> + </div> + </div> + + <!-- Add Chore --> + <div + id="add-chore" + class="flex flex-row items-center p-1" + :class="{ + 'justify-center': !addingChore, + }" + v-if="!onDashboard" + > + <div + class="rounded-full shadow-lg bg-neutral-100 hover:scale-110 hover:drop-shadow-lg hover:cursor-pointer px-1 py-1 text-xl flex items-center justify-center" + @click="addChore" + v-if="!addingChore" + > + <FontAwesomeIcon + :icon="faCirclePlus" + class="hover:cursor-pointer text-xl justify-center" + /> + </div> + <div + v-else + class="flex flex-row w-full items-center bg-secondary-200 shadow-lg rounded-xl p-2 mx-3" + > + <div class="w-3/12"> + <input + v-focus + v-on:keyup.enter="saveNewChore" + type="text" + v-model="addingChore.chore_name" + placeholder="Aufgabe" + class="rounded-xl px-4 shadow-lg py-0 bg-secondary-50 border-none focus:ring-2 focus:ring-secondary-600 w-4/5 indie-flower-regular text-lg" + :class="{ + 'border-red-600 border-4': addingChore.chore_name === '', + }" + /> + </div> + <div class="w-3/12"> + am + <input + id="adding-chore-date-picker" + v-on:keyup.enter="saveNewChore" + type="text" + v-model="addingChore.chore_date" + class="rounded-xl mx-1 px-2 shadow-lg py-0 bg-secondary-50 border-none focus:ring-2 focus:ring-secondary-600 w-1/2" + /> + </div> + <div class="w-3/12 gap-1 flex"> + alle + <input + v-on:keyup.enter="saveNewChore" + type="number" + min="1" + v-model="addingChore.chore_frequency" + class="rounded-xl shadow-lg py-0 bg-secondary-50 border-none focus:ring-2 focus:ring-secondary-600 w-1/6" + /> + <select + v-on:keyup.enter="saveNewChore" + v-model="addingChore.chore_frequency_unit" + class="rounded-xl shadow-lg py-0 bg-secondary-50 border-none focus:ring-2 focus:ring-secondary-600 w-3/6" + > + <option value="Tage">Tage</option> + <option value="Wochen">Wochen</option> + <option value="Monate">Monate</option> + </select> + </div> + <div class="w-2/12"> + <select + v-on:keyup.enter="saveNewChore" + v-model="addingChore.chore_user" + class="rounded-xl px-3 shadow-lg py-0 bg-secondary-50 border-none focus:ring-2 focus:ring-secondary-600 w-7/12" + :class="{ + 'border-red-600 border-4': addingChore.chore_user === '', + }" + > + <option value="" disabled>Nutzer</option> + <option + v-for="user in users" + :value="user.user_id" + :key="user.user_id" + > + {{ user.username }} + </option> + </select> + </div> + + <div class="flex grow"></div> + <div id="add-chore-actions" class="flex flex-row gap-2 pr-3"> + <div + class="rounded-xl shadow-lg bg-secondary-100 hover:scale-110 hover:drop-shadow-lg hover:cursor-pointer px-1" + v-if=" + addingChore.chore_name === '' || addingChore.chore_user === '' + " + > + <FontAwesomeIcon + :icon="faTriangleExclamation" + class="text-red-600" + /> + </div> + <div + class="rounded-xl shadow-lg bg-secondary-100 hover:scale-110 hover:drop-shadow-lg hover:cursor-pointer px-1" + @click="saveNewChore" + > + <FontAwesomeIcon :icon="faCheck" class="hover:cursor-pointer" /> + </div> + <div + class="rounded-xl shadow-lg bg-secondary-100 hover:scale-110 hover:drop-shadow-lg hover:cursor-pointer px-1" + @click="addingChore = null" + > + <FontAwesomeIcon :icon="faTimes" class="px-0.5" /> + </div> + </div> + </div> + </div> + </div> +</template> + +<script lang="ts"> +interface Chore { + chore_id: number; + chore_name: string; + chore_user: number; + chore_date: string; + chore_done: boolean; +} +interface User { + user_id: number; + username: string; +} + +var unitConversion = { + Tage: "days", + Wochen: "weeks", + Monate: "months", +}; + +export default { + data() { + return { + allChores: [] as Chore[], + editingChore: null as Chore | null, + addingChore: null as Chore | null, + users: [] as User[], + }; + }, + props: { onDashboard: Boolean, currDate: Date }, + methods: { + forwardChore(chore: Chore) { + // change date to next date + let newDate: string = format( + add(chore.chore_date, { + [unitConversion[chore.chore_frequency_unit]]: chore.chore_frequency, + }), + "yyyy-MM-dd", + ); + let newUser: number = + this.users[ + (this.users.findIndex((user) => user.user_id === chore.chore_user) + + 1) % + this.users.length + ].user_id; + + fetch(`http://localhost:8000/chores/${chore.chore_id}/`, { + method: "PATCH", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + chore_date: newDate, + chore_user: newUser, + }), + }).then(() => { + chore.chore_date = newDate; + chore.chore_user = newUser; + }); + }, + cancelEditChore(chore: Chore) { + this.editingChore = null; + }, + backwardChore(chore: Chore) { + // change date to previous date + let newDate: string = format( + add(chore.chore_date, { + [unitConversion[chore.chore_frequency_unit]]: -chore.chore_frequency, + }), + "yyyy-MM-dd", + ); + + let newUser: number = + this.users[ + (this.users.findIndex((user) => user.user_id === chore.chore_user) + + this.users.length - + 1) % + this.users.length + ].user_id; + + fetch(`http://localhost:8000/chores/${chore.chore_id}/`, { + method: "PATCH", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + chore_date: newDate, + chore_user: newUser, + }), + }).then(() => { + chore.chore_date = newDate; + chore.chore_user = newUser; + }); + }, + addChore() { + this.addingChore = { + chore_name: "", + chore_user: "", + chore_date: format(new Date(), "yyyy-MM-dd"), + chore_done: false, + chore_frequency: 1, + chore_frequency_unit: "Wochen", + }; + this.$nextTick(() => { + new AirDatepicker("#adding-chore-date-picker", { + selectedDates: [new Date()], + locale: localeDe, + dateFormat: "dd.MM.yyyy", + onSelect: (ret) => { + console.log(ret.date); + console.log(ret.formattedDate); + this.addingChore.chore_date = format(ret.date, "yyyy-MM-dd"); + }, + }); + }); + }, + saveNewChore() { + if ( + this.addingChore.chore_name === "" || + this.addingChore.chore_user === "" + ) { + return; + } + + fetch("http://localhost:8000/chores/", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(this.addingChore), + }).then(() => { + this.allChores.push(this.addingChore); + this.addingChore = null; + }); + }, + editChore(chore: Chore) { + this.editingChore = chore; + //wait for next tick to create the datepicker + this.$nextTick(() => { + new AirDatepicker("#chore-date-picker", { + selectedDates: [new Date(chore.chore_date)], + locale: localeDe, + dateFormat: "dd.MM.yyyy", + onSelect: (ret) => { + console.log(ret.date); + console.log(ret.formattedDate); + this.editingChore.chore_date = format(ret.date, "yyyy-MM-dd"); + }, + }); + }); + }, + saveChore(chore: Chore) { + fetch(`http://localhost:8000/chores/${chore.chore_id}/`, { + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(chore), + }).then(() => { + chore = this.editingChore; + this.editingChore = null; + }); + }, + deleteChore(chore: Chore) { + fetch(`http://localhost:8000/chores/${chore.chore_id}/`, { + method: "DELETE", + }).then(() => { + this.allChores = this.allChores.filter( + (c: Chore) => c.chore_id !== chore.chore_id, + ); + }); + }, + isOverdue(date: Date) { + console.log(this.chores); + // console.log("isOverdue"); + // console.log(date); + return this.compareDates(date, new Date()) < 0; + }, + compareDates(date1: Date, date2: Date) { + let dateString1 = this.compareFormat(date1); + let dateString2 = this.compareFormat(date2); + if (dateString1 < dateString2) { + return -1; + } else if (dateString1 > dateString2) { + return 1; + } else { + return 0; + } + }, + getUserName(userId: number) { + let user = this.users.find((user) => user.user_id === userId); + return user ? user.username : ""; + }, + compareFormat(date: Date) { + return format(date, "yyyy-MM-dd"); + }, + formatDate(date: Date | string) { + let theDate: Date; + if (typeof date === "string") { + theDate = new Date(date); + } + return format(theDate, "dd.MM.yyyy"); + }, + }, + computed: { + chores() { + if (this.onDashboard) { + return this.allChores + .filter((chore: Chore) => { + return ( + this.compareDates(new Date(chore.chore_date), this.currDate) <= 0 + ); + }) + .sort((a: Chore, b: Chore) => { + return compareAsc(a.chore_date, b.chore_date); + }); + } else { + return this.allChores + .sort((a: Chore, b: Chore) => { + a.chore_id - b.chore_id; + }) + .sort((a: Chore, b: Chore) => { + return compareAsc(a.chore_date, b.chore_date); + }); + } + }, + }, + async mounted() { + fetch("http://localhost:8000/chores/") + .then((response) => response.json()) + .then((data) => { + this.allChores = data; + }); + fetch("http://localhost:8000/users/") + .then((response) => response.json()) + .then((data) => { + // sort by id to keep the order consistent + this.users = data.sort((a: User, b: User) => a.user_id - b.user_id); + }); + }, +}; +</script> diff --git a/chorechef_frontend/src/components/Chores.vue.old b/chorechef_frontend/src/components/Chores.vue.old new file mode 100644 index 0000000000000000000000000000000000000000..a252625a9232378317583cec7052f29004198aa6 --- /dev/null +++ b/chorechef_frontend/src/components/Chores.vue.old @@ -0,0 +1,452 @@ +<script setup lang="ts"> +import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; +import { + faCirclePlus, + faCheck, + faTrash, + faPenToSquare, + faCaretUp, + faCaretDown, + faTimes, + faFloppyDisk, +} from "@fortawesome/free-solid-svg-icons"; +import { format, add } from "date-fns"; +import AirDatepicker from "air-datepicker"; +import "air-datepicker/air-datepicker.css"; +import localeDe from "air-datepicker/locale/de"; +</script> +<template> + <h2 class="font-bold p-1">Aufgaben</h2> + <div id="chores" class="flex flex-col shrink gap-1 p-1"> + <div + v-for="chore in chores" + class="chore items-center" + :class="{ + 'text-red-600': + chore.chore_date < compareFormatDate(new Date().toISOString()), + }" + > + <div + class="w-full border border-black rounded p-1 flex flex-row gap-4 items-center" + v-if=" + !onDashboard || + (chore.chore_date <= compareFormatDate(currDate.toISOString()) && + !chore.chore_done) + " + > + <div + v-if="onDashboard" + class="chore-checkbox border border-black w-4 h-4 rounded bg-gray-50 hover:cursor-pointer flex justify-center items-center" + @click="toggleChore(chore)" + > + <FontAwesomeIcon :icon="faCheck" v-if="chore.chore_done" /> + </div> + <div + class="chore-name w-1/4" + v-if="editChore.chore_id != chore.chore_id" + > + {{ chore.chore_name }} | {{ editChore.chore_id }} | + {{ chore.chore_id }} + </div> + <input + v-else + v-focus + v-model="editChore.chore_name" + type="text" + class="chore-name-input pl-2 pr-2 w-1/4 flex flex-row gap-1 border border-black rounded bg-gray-50" + /> + <div + class="chore-date w-[6.25rem]" + v-if="editChore.chore_id != chore.chore_id" + > + {{ formatDate(chore.chore_date) }} + </div> + <input + id="edit-date-picker" + type="text" + class="chore-date-input px-1 w-[6.25rem] bg-gray-50 border border-black rounded hover:cursor-pointer" + readonly + v-else + /> + <div + v-if="editChore.chore_id != chore.chore_id" + class="chore-frequency" + > + alle {{ chore.chore_frequency }} {{ chore.chore_frequency_unit }} + </div> + <div v-else class="flex flex-row gap-1"> + <label for="chore-frequency" class="flex flex-row shrink gap-1"> + alle + <input + v-model="editChore.chore_frequency" + type="number" + class="chore-frequency-input w-12 px-1 bg-gray-50 border border-black rounded hover:cursor-text" + /> + <select + v-model="editChore.chore_frequency_unit" + class="chore-frequency-input flex flex-row gap-1 bg-gray-50 border border-black rounded hover:cursor-pointer" + > + <option value="Tage" class="hover:cursor-pointer">Tage</option> + <option value="Wochen" class="hover:cursor-pointer"> + Wochen + </option> + <option value="Monate" class="hover:cursor-pointer"> + Monate + </option> + </select> + </label> + </div> + + <div class="px-4"> + {{ users.find((u) => u.user_id == chore.chore_user)?.username }} + </div> + + <div class="grow"></div> + <FontAwesomeIcon + v-if="editChore.chore_id == chore.chore_id" + :icon="faTimes" + class="hover:cursor-pointer pr-2 hover:text-green-600" + @click="cancelEditing" + /> + <FontAwesomeIcon + v-if="editChore.chore_id == chore.chore_id" + :icon="faFloppyDisk" + class="hover:cursor-pointer pr-2 hover:text-green-600" + @click="endEditing" + /> + <FontAwesomeIcon + v-if="!onDashboard && editChore.chore_id != chore.chore_id" + :icon="faPenToSquare" + class="hover:cursor-pointer pr-2" + @click="startEditing(chore)" + /> + <FontAwesomeIcon + v-if="!onDashboard" + :icon="faTrash" + class="hover:cursor-pointer pr-2 hover:text-red-600" + @click="deleteChore(chore)" + /> + </div> + </div> + </div> + <div + v-if="!onDashboard" + id="add-chore" + class="flex flex-row gap-4 p-1 justify-center" + > + <FontAwesomeIcon + v-if="!adding" + @click="startAdding" + :icon="faCirclePlus" + class="hover:cursor-pointer text-2xl" + /> + <div class="flex flex-row items-center gap-2 px-2 w-full" v-else> + <input + v-focus + v-model="newChore.chore_name" + type="text" + class="chore-name-input pl-2 pr-2 w-1/3 flex flex-row gap-1 bg-gray-50 border border-black rounded" + placeholder="Neue Aufgabe" + /> + <label for="date-picker" class="flex flex-row shrink gap-1"> + erste Ausführung am + <input + id="date-picker" + type="text" + class="chore-date-input px-1 w-[6.25rem] bg-gray-50 border border-black rounded hover:cursor-pointer" + readonly + /> + </label> + <label for="chore-frequency" class="flex flex-row shrink gap-1"> + alle + <input + v-model="newChore.chore_frequency" + type="number" + class="chore-frequency-input w-12 px-1 bg-gray-50 border border-black rounded hover:cursor-text" + /> + </label> + <select + v-model="newChore.chore_frequency_unit" + class="chore-frequency-input flex flex-row gap-1 bg-gray-50 border border-black rounded hover:cursor-pointer" + > + <option value="Tage" class="hover:cursor-pointer">Tage</option> + <option value="Wochen" class="hover:cursor-pointer">Wochen</option> + <option value="Monate" class="hover:cursor-pointer">Monate</option> + </select> + + <select + v-model="newChore.chore_user" + class="chore-user-input flex flex-row gap-1 bg-gray-50 border border-black rounded hover:cursor-pointer" + > + <option + v-for="user in users" + :value="user.user_id" + class="hover:cursor-pointer" + > + {{ user.username }} + </option> + </select> + + <div class="flex-grow"></div> + <FontAwesomeIcon + :icon="faTimes" + @click="adding = false" + class="hover:cursor-pointer px-2 hover:text-red-600" + /> + <FontAwesomeIcon + :icon="faCheck" + @click="endAdding" + class="hover:cursor-pointer px-2 hover:text-green-600" + /> + </div> + </div> + <div v-if="onDashboard" class="done-chores"> + <h3 class="font-bold p-1 hover:cursor-pointer" @click="toggleDoneChores"> + Erledigte Aufgaben + <FontAwesomeIcon :icon="faCaretDown" v-if="!showDone" /> + <FontAwesomeIcon :icon="faCaretUp" v-if="showDone" /> + </h3> + <div v-if="showDone" class="flex flex-col gap-1 p-1"> + <div + v-for="chore in chores.filter((c) => c.chore_done)" + class="flex flex-row shrink gap-4 border border-black rounded p-1 italic line-through text-gray-500 items-center" + > + <div + v-if="onDashboard" + class="chore-checkbox border border-black w-4 h-4 rounded bg-gray-50 hover:cursor-pointer flex justify-center items-center" + @click="toggleChore(chore)" + > + <FontAwesomeIcon :icon="faCheck" v-if="chore.chore_done" /> + </div> + <div class="chore-name w-1/4">{{ chore.chore_name }}</div> + <div class="chore-date">{{ formatDate(chore.chore_date) }}</div> + <div class="chore-frequency"> + alle {{ chore.chore_frequency }} {{ chore.chore_frequency_unit }} + </div> + + <div class="grow"></div> + </div> + </div> + </div> +</template> + +<script lang="ts"> +interface Chore { + chore_id: number; + chore_name: string; + chore_date: string; + chore_frequency: string; + chore_frequency_unit: string; + chore_done: boolean; + chore_user: number; +} +interface User { + user_id: number; + username: string; +} +export default { + name: "Chores", + data() { + return { + chores: [] as Chore[], + users: [] as User[], + adding: false, + newChore: {} as Chore, + editChore: {} as Chore, + rollBackChore: {} as Chore, + showDone: false, + unitConversion: { + Tage: "days", + Wochen: "weeks", + Monate: "months", + }, + }; + }, + props: { + currDate: Date, + onDashboard: Boolean, + }, + methods: { + toggleDoneChores() { + this.showDone = !this.showDone; + }, + async fetchChores() { + const response = await fetch("http://localhost:8000/chores/"); + const chores = await response.json(); + if (this.onDashboard) { + this.chores = chores.sort((a, b) => + a.chore_date.localeCompare(b.chore_date), + ); + } else { + this.chores = chores; + } + }, + startEditing(chore: Chore) { + this.editChore = chore; + this.rollBackChore = { ...chore }; + this.$nextTick(() => { + new AirDatepicker("#edit-date-picker", { + selectedDates: [new Date(chore.chore_date)], + locale: localeDe, + onSelect: (rec) => { + this.editChore.chore_date = format(rec.date, "yyyy-MM-dd"); + }, + }); + }); + }, + cancelEditing() { + this.editChore = this.rollBackChore; + this.rollBackChore = {} as Chore; + this.endEditing(); + // reflect the changes in the UI + this.fetchChores(); + }, + endEditing() { + fetch(`http://localhost:8000/chores/${this.editChore.chore_id}/`, { + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(this.editChore), + }); + this.editChore = {} as Chore; + this.rollBackChore = {} as Chore; + }, + startAdding() { + this.adding = true; + this.newChore.chore_date = format(new Date(), "yyyy-MM-dd"); + this.newChore.chore_frequency = 1; + this.newChore.chore_frequency_unit = "Wochen"; + this.newChore.chore_done = false; + // pause until the element is rendered + this.$nextTick(() => { + new AirDatepicker("#date-picker", { + selectedDates: [new Date()], + locale: localeDe, + onSelect: (rec) => { + this.newChore.chore_date = format(rec.date, "yyyy-MM-dd"); + }, + }); + }); + }, + endAdding() { + console.log(this.newChore); + fetch("http://localhost:8000/chores/", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + chore_name: this.newChore.chore_name, + chore_date: this.newChore.chore_date, + chore_frequency: this.newChore.chore_frequency, + chore_frequency_unit: this.newChore.chore_frequency_unit, + chore_done: false, + chore_user: this.newChore.chore_user, + }), + }); + this.chores.push(this.newChore); + this.newChore = {} as Chore; + this.adding = false; + }, + deleteChore(chore: Chore) { + fetch(`http://localhost:8000/chores/${chore.chore_id}/`, { + method: "DELETE", + }); + this.chores = this.chores.filter((c) => c.chore_id !== chore.chore_id); + }, + toggleChore(chore: Chore) { + chore.chore_done = !chore.chore_done; + this.updateDonePastChores(chore); + fetch(`http://localhost:8000/chores/${chore.chore_id}/`, { + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(chore), + }); + }, + formatDate(date: string) { + return format(new Date(date), "d.M.yy"); + }, + compareFormatDate(date: string) { + return format(new Date(date), "yyyy-MM-dd"); + }, + moveChoreBack(chore: Chore) { + let unit = this.unitConversion[chore.chore_frequency_unit]; + let updatedChore = { + chore_id: chore.chore_id, + chore_name: chore.chore_name, + chore_date: this.compareFormatDate( + add(new Date(chore.chore_date), { + [unit]: -chore.chore_frequency, + }).toISOString(), + "yyyy-MM-dd", + ), + chore_frequency: chore.chore_frequency, + chore_frequency_unit: chore.chore_frequency_unit, + chore_done: false, + } as Chore; + this.chores.push(updatedChore); + fetch(`http://localhost:8000/chores/${chore.chore_id}/`, { + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(updatedChore), + }); + }, + updateDonePastChores(chore) { + console.log("updateDonePastChores"); + if ( + chore.chore_date < this.compareFormatDate(new Date().toISOString()) && + chore.chore_done + ) { + let unit = this.unitConversion[chore.chore_frequency_unit]; + + let updatedChore = { + chore_id: chore.chore_id, + chore_name: chore.chore_name, + chore_date: this.compareFormatDate( + add(new Date(chore.chore_date), { + [unit]: chore.chore_frequency, + }).toISOString(), + ), + chore_frequency: chore.chore_frequency, + chore_frequency_unit: chore.chore_frequency_unit, + chore_done: false, + chore_user: chore.chore_user, + } as Chore; + console.log(this.chores); + console.log(updatedChore); + this.chores.push(updatedChore); + console.log(this.chores); + fetch(`http://localhost:8000/chores/${chore.chore_id}/`, { + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(updatedChore), + }); + } + }, + fetchUsers() { + fetch("http://localhost:8000/users/").then((response) => { + response.json().then((users) => { + this.users = users.sort((a, b) => a.user_id - b.user_id); + console.log(this.users); + }); + }); + }, + }, + async mounted() { + await this.fetchChores(); + this.fetchUsers(); + }, + watch: { + currDate() { + this.fetchChores(); + }, + }, +}; +</script> diff --git a/chorechef_frontend/src/components/Dashboard.vue b/chorechef_frontend/src/components/Dashboard.vue new file mode 100644 index 0000000000000000000000000000000000000000..8c02dc6e67f96480e788af0d198399a1e03d31c2 --- /dev/null +++ b/chorechef_frontend/src/components/Dashboard.vue @@ -0,0 +1,5 @@ +<script setup lang="ts"></script> + +<template> + <h1 class="text-4xl p-2 font-bold">ChoreChef</h1> +</template> diff --git a/chorechef_frontend/src/components/DashboardMeals.vue b/chorechef_frontend/src/components/DashboardMeals.vue new file mode 100644 index 0000000000000000000000000000000000000000..bf329ec86a066aad521c4db1b272a49372cb5429 --- /dev/null +++ b/chorechef_frontend/src/components/DashboardMeals.vue @@ -0,0 +1,54 @@ +<script setup lang="ts"></script> +<template> + <h2 class="font-bold p-1">Essensplan</h2> + <div id="meals" class="flex flex-row grow gap-1 p-1"> + <div class="meal flex flex-col gap-1 w-1/4 border border-black rounded p-1"> + <div + class="meal-name h-2/6 text-xl font-bold border border-black rounded flex justify-center items-center" + > + Kassler + </div> + <div + class="meal-notices text-sm break-normal h-4/6 border border-black rounded p-0.5" + > + Lexker Schmecker po palekker + </div> + </div> + <div class="meal flex flex-col gap-1 w-1/4 border border-black rounded p-1"> + <div + class="meal-name h-2/6 text-xl font-bold border border-black rounded flex justify-center items-center" + > + Kassler + </div> + <div + class="meal-notices text-sm break-normal h-4/6 border border-black rounded p-0.5" + > + Lexker Schmecker po palekker + </div> + </div> + <div class="meal flex flex-col gap-1 w-1/4 border border-black rounded p-1"> + <div + class="meal-name h-2/6 text-xl font-bold border border-black rounded flex justify-center items-center" + > + Kassler + </div> + <div + class="meal-notices text-sm break-normal h-4/6 border border-black rounded p-0.5" + > + Lexker Schmecker po palekker + </div> + </div> + <div class="meal flex flex-col gap-1 w-1/4 border border-black rounded p-1"> + <div + class="meal-name h-2/6 text-xl font-bold border border-black rounded flex justify-center items-center" + > + Kassler + </div> + <div + class="meal-notices text-sm break-normal h-4/6 border border-black rounded p-0.5" + > + Lexker Schmecker po palekker + </div> + </div> + </div> +</template> diff --git a/chorechef_frontend/src/components/DashboardTasks.vue b/chorechef_frontend/src/components/DashboardTasks.vue new file mode 100644 index 0000000000000000000000000000000000000000..2316d62fa14809f47648c54e7fcf0328c5e78be8 --- /dev/null +++ b/chorechef_frontend/src/components/DashboardTasks.vue @@ -0,0 +1,46 @@ +<script setup lang="ts"></script> +<template> + <h2 class="font-bold p-1">Aufgaben</h2> + <div id="tasks" class="flex flex-col grow gap-1 p-1"> + <div + class="task flex flex-row gap-4 border border-black rounded p-1 items-center" + > + <div + class="task-checkbox border border-black w-4 h-4 rounded bg-gray-50" + ></div> + <div class="task-name flex-grow">Wohnzimmer saugen</div> + </div> + <div + class="task flex flex-row gap-4 border border-black rounded p-1 items-center" + > + <div + class="task-checkbox border border-black w-4 h-4 rounded bg-gray-50" + ></div> + <div class="task-name flex-grow">Wohnzimmer saugen</div> + </div> + <div + class="task flex flex-row gap-4 border border-black rounded p-1 items-center" + > + <div + class="task-checkbox border border-black w-4 h-4 rounded bg-gray-50" + ></div> + <div class="task-name flex-grow">Wohnzimmer saugen</div> + </div> + <div + class="task flex flex-row gap-4 border border-black rounded p-1 items-center" + > + <div + class="task-checkbox border border-black w-4 h-4 rounded bg-gray-50" + ></div> + <div class="task-name flex-grow">Wohnzimmer saugen</div> + </div> + <div + class="task flex flex-row gap-4 border border-black rounded p-1 items-center" + > + <div + class="task-checkbox border border-black w-4 h-4 rounded bg-gray-50" + ></div> + <div class="task-name flex-grow">Wohnzimmer saugen</div> + </div> + </div> +</template> diff --git a/chorechef_frontend/src/components/Mealplan.vue b/chorechef_frontend/src/components/Mealplan.vue new file mode 100644 index 0000000000000000000000000000000000000000..85b164c68937d4dca0a1f7419b0660a039f0978e --- /dev/null +++ b/chorechef_frontend/src/components/Mealplan.vue @@ -0,0 +1,227 @@ +<script setup lang="ts"> +import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; +import { + faPenToSquare, + faTimes, + faSave, + faTrash, +} from "@fortawesome/free-solid-svg-icons"; +import { ref } from "vue"; +</script> + +<template> + <div + id="meals" + class="flex flex-row grow gap-2 p-2 bg-primary-400 shadow-lg rounded-xl m-2" + > + <div + class="meal flex flex-col gap-4 w-1/4 rounded-xl p-2 shadow-lg bg-primary-300" + v-for="n in numMeals" + > + <div class="flex flex-row"> + <div + class="meal-date text-xl font-bold flex justify-center bg-primary-200 rounded-xl shadow-lg grow" + > + {{ dateOnPos(n) }} + </div> + <div v-if="!onDashboard" class="grow"></div> + <div v-if="!onDashboard" class="flex flex-row gap-1"> + <div + class="edit-button flex p-1.5 items-center bg-primary-100 rounded-full shadow-lg hover:cursor-pointer hover:scale-110 hover:text-neutral-900 transition hover:drop-shadow-lg" + v-if="editingMeal && editingMeal.meal_date === compDateOnPos(n)" + @click="saveMeal" + > + <FontAwesomeIcon :icon="faSave" class="hover:cursor-pointer" /> + </div> + <div + class="edit-button flex p-1.5 items-center bg-primary-100 rounded-full shadow-lg hover:cursor-pointer hover:scale-110 hover:text-neutral-900 transition hover:drop-shadow-lg" + v-if="editingMeal && editingMeal.meal_date === compDateOnPos(n)" + @click="cancelEditing" + > + <FontAwesomeIcon :icon="faTimes" class="hover:cursor-pointer" /> + </div> + <div v-else class="flex flex-row gap-1"> + <div + class="edit-button flex p-1.5 items-center bg-primary-100 rounded-full shadow-lg hover:cursor-pointer hover:scale-110 hover:text-neutral-900 transition hover:drop-shadow-lg" + @click="startEditing(n)" + > + <FontAwesomeIcon :icon="faPenToSquare" /> + </div> + <div + class="edit-button flex p-1.5 items-center bg-primary-100 rounded-full shadow-lg hover:cursor-pointer hover:scale-110 hover:text-neutral-900 transition hover:drop-shadow-lg" + @click="deleteMeal(n)" + > + <FontAwesomeIcon :icon="faTrash" /> + </div> + </div> + </div> + </div> + <input + v-focus + v-if="editingMeal && editingMeal.meal_date === compDateOnPos(n)" + v-model="editingMeal.meal_name" + class="meal-name-input p-2 h-2/6 w-full bg-primary-50 rounded-xl shadow-lg border-none transition focus:ring-2 focus:ring-primary-500 indie-flower-bold text-center text-3xl" + placeholder="Neues Gericht" + /> + <div + v-else + class="meal-name h-2/6 text-3xl font-bold flex flex-col justify-center rounded-xl shadow-lg bg-primary-100 indie-flower-bold text-center" + > + {{ + meals.find( + (meal) => + meal.meal_date === + format(add(currDate, { days: n - 1 }), "yyyy-MM-dd"), + )?.meal_name + }} + </div> + <textarea + v-model="editingMeal.meal_description" + v-if="editingMeal && editingMeal.meal_date === compDateOnPos(n)" + class="meal-description-input p-2 h-4/6 flex flex-row gap-1 bg-primary-50 rounded-xl shadow-lg border-none transition focus:ring-2 focus:ring-primary-500 indie-flower-regular text-lg" + ></textarea> + + <div + v-else + class="meal-notice text-lg break-normal h-4/6 p-2 indie-flower-regular bg-primary-100 shadow-lg rounded-xl" + > + {{ + meals.find( + (meal) => + meal.meal_date === + format(add(currDate, { days: n - 1 }), "yyyy-MM-dd"), + )?.meal_description + }} + </div> + </div> + </div> +</template> + +<script lang="ts"> +import { format, add, setDefaultOptions } from "date-fns"; +import { de } from "date-fns/locale"; +setDefaultOptions({ locale: de }); +interface Meal { + meal_name: string; + meal_description: string; + meal_date: string; + meal_image: string | null; +} + +export default { + data() { + return { + meals: [] as Meal[], + editingMeal: null as Meal | null, + rollBackMeal: null as Meal | null, + }; + }, + props: { + onDashboard: Boolean, + currDate: Date, + }, + computed: { + numMeals: function () { + if (this.onDashboard) { + return 4; + } else { + return 7; + } + }, + }, + methods: { + mealOnPos(n: int) { + console.log("mealOnPos"); + const date = format(add(this.currDate, { days: n - 1 }), "yyyy-MM-dd"); + return ( + this.meals.find((meal) => meal.meal_date === date) || { + meal_name: "", + meal_description: "", + meal_date: date, + meal_image: null, + } + ); + }, + dateOnPos(n: int) { + return format(add(this.currDate, { days: n - 1 }), "EEEEEE, d. MMM"); + }, + compDateOnPos(n: int) { + return format(add(this.currDate, { days: n - 1 }), "yyyy-MM-dd"); + }, + + async fetchMeals() { + const response = await fetch("http://localhost:8000/meals"); + const data = await response.json(); + return data as Meal[]; + }, + startEditing(n: int) { + this.editingMeal = this.mealOnPos(n); + this.rollBackMeal = { ...this.editingMeal }; + }, + deleteMeal(n: int) { + const date = format(add(this.currDate, { days: n - 1 }), "yyyy-MM-dd"); + const index = this.meals.findIndex((meal) => meal.meal_date === date); + if (index !== -1) { + this.meals.splice(index, 1); + } + fetch(`http://localhost:8000/meals/${date}/`, { + method: "DELETE", + }); + }, + async saveMeal() { + const index = this.meals.findIndex( + (meal) => meal.meal_date === this.editingMeal!.meal_date, + ); + if (index !== -1) { + this.meals.splice(index, 1, this.editingMeal!); + } + + //Update the meal or create a new one in database + console.log(JSON.stringify(this.editingMeal)); + + if (index === -1) { + let resp = await fetch("http://localhost:8000/meals/", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(this.editingMeal), + }); + console.log(resp); + console.log(resp.json()); + } else { + fetch(`http://localhost:8000/meals/${this.editingMeal!.meal_date}/`, { + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(this.editingMeal), + }); + } + + this.meals = await this.fetchMeals(); + + this.editingMeal = null; + this.rollBackMeal = null; + }, + cancelEditing() { + console.log(this.rollBackMeal); + const index = this.meals.findIndex( + (meal) => meal.meal_date === this.editingMeal!.meal_date, + ); + if (index !== -1) { + this.meals.splice(index, 1, this.rollBackMeal!); + } + this.editingMeal = null; + this.rollBackMeal = null; + }, + }, + async mounted() { + const meals = await this.fetchMeals(); + this.meals = meals; + }, + created() { + console.log(this.currDate); + }, +}; +</script> diff --git a/chorechef_frontend/src/components/Settings.vue b/chorechef_frontend/src/components/Settings.vue new file mode 100644 index 0000000000000000000000000000000000000000..361300dbdba24bdba5abf6938173ee2e33de00d4 --- /dev/null +++ b/chorechef_frontend/src/components/Settings.vue @@ -0,0 +1,162 @@ +<script setup lang="ts"> +import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; +import { + faUser, + faTrash, + faCirclePlus, + faTimes, + faFloppyDisk, + faPenToSquare, +} from "@fortawesome/free-solid-svg-icons"; +</script> +<template> + <div class="bg-neutral-400 grow"> + <h1 class="text-4xl p-3 font-bold">Einstellungen</h1> + <div + class="p-4 w-1/3 rounded-xl mx-4 flex flex-col gap-4 bg-neutral-300 shadow-lg" + > + <h2 class="text-2xl font-bold"> + <FontAwesomeIcon :icon="faUser" /> Nutzer + </h2> + <div + v-for="user in users" + class="flex flex-row gap-4 bg-neutral-200 rounded-xl shadow-lg p-2 items-center" + > + <input + v-focus + v-on:keyup.enter="updateUser(user)" + type="text" + v-model="userToEdit.username" + placeholder="Nutzername" + class="border-none rounded-xl py-0 bg-neutral-50 focus:ring-2 focus:ring-neutral-600 shadow-lg w-1/2" + v-if="userToEdit === user" + /> + <p v-else class="px-3 bg-neutral-100 rounded-xl shadow-lg w-1/2"> + {{ user.username }} + </p> + <div class="grow"></div> + <div + class="rounded-xl shadow-lg bg-neutral-100 hover:scale-110 hover:drop-shadow-lg hover:cursor-pointer px-1 transition" + @click="editUser(user)" + v-if="!userToEdit" + > + <FontAwesomeIcon :icon="faPenToSquare" class="px-0.5" /> + </div> + <div + class="rounded-xl shadow-lg bg-neutral-100 hover:scale-110 hover:drop-shadow-lg hover:cursor-pointer px-1 transition" + @click="updateUser(user)" + v-if="userToEdit === user" + > + <FontAwesomeIcon :icon="faFloppyDisk" class="px-0.5" /> + </div> + <div + class="rounded-xl shadow-lg bg-neutral-100 hover:scale-110 hover:drop-shadow-lg hover:cursor-pointer px-1 transition" + @click="deleteUser(user)" + > + <FontAwesomeIcon :icon="faTrash" class="px-0.5" /> + </div> + </div> + + <div class="flex flex-grow justify-center"> + <div + class="rounded-full shadow-lg bg-neutral-100 hover:scale-110 hover:drop-shadow-lg hover:cursor-pointer px-1 py-2 text-xl flex items-center justify-center transition" + @click="addUser" + v-if="!userToAdd" + > + <FontAwesomeIcon :icon="faCirclePlus" class="px-1" /> + </div> + <div + v-if="userToAdd" + class="flex flex-row grow gap-4 bg-neutral-200 rounded-xl shadow-lg p-2 items-center" + > + <input + v-focus + v-on:keyup.enter="saveUser" + type="text" + v-model="userToAdd.username" + placeholder="Nutzername" + class="border-none rounded-xl py-0 bg-neutral-50 focus:ring-2 focus:ring-neutral-600 shadow-lg w-1/2" + /> + <div class="grow"></div> + <div + class="rounded-xl shadow-lg bg-neutral-100 hover:scale-110 hover:drop-shadow-lg hover:cursor-pointer px-1 transition" + @click="saveUser" + > + <FontAwesomeIcon :icon="faFloppyDisk" class="px-0.5" /> + </div> + + <div + class="rounded-xl shadow-lg bg-neutral-100 hover:scale-110 hover:drop-shadow-lg hover:cursor-pointer px-1 transition" + @click="userToAdd = null" + > + <FontAwesomeIcon :icon="faTimes" class="px-0.5 text-lg" /> + </div> + </div> + </div> + </div> + </div> +</template> + +<script lang="ts"> +interface User { + user_id: number; + username: string; +} +export default { + name: "Settings", + data() { + return { + users: [] as User[], + userToAdd: null as User | null, + userToEdit: null as User | null, + }; + }, + methods: { + async fetchUsers() { + const response = await fetch("http://localhost:8000/users/"); + this.users = await response.json(); + }, + addUser() { + this.userToAdd = {}; + }, + editUser(user: User) { + this.userToEdit = user; + }, + deleteUser(user: User) { + fetch("http://localhost:8000/users/" + user.user_id + "/", { + method: "DELETE", + }).then(() => { + this.fetchUsers(); + }); + }, + updateUser(user: User) { + console.log(user); + fetch("http://localhost:8000/users/" + user.user_id + "/", { + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(user), + }).then(() => { + this.fetchUsers(); + this.userToEdit = null; + }); + }, + saveUser() { + fetch("http://localhost:8000/users/", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(this.userToAdd), + }).then(() => { + this.fetchUsers(); + this.userToAdd = null; + }); + }, + }, + mounted() { + this.fetchUsers(); + }, +}; +</script> diff --git a/chorechef_frontend/src/main.ts b/chorechef_frontend/src/main.ts new file mode 100644 index 0000000000000000000000000000000000000000..06954250682108fe3d2fe18bd58e6345a0ca704a --- /dev/null +++ b/chorechef_frontend/src/main.ts @@ -0,0 +1,18 @@ +import "./assets/main.css"; + +import { createApp } from "vue"; +import App from "./App.vue"; +import router from "./router"; + +const app = createApp(App); + +app.use(router); + +app.directive("focus", { + mounted(el) { + // When the bound element is inserted into the DOM... + el.focus(); // Focus the element + }, +}); + +app.mount("#app"); diff --git a/chorechef_frontend/src/router/index.ts b/chorechef_frontend/src/router/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..91f32d669ae68cd431fc6a154d0e28fc9dcd1a86 --- /dev/null +++ b/chorechef_frontend/src/router/index.ts @@ -0,0 +1,36 @@ +import { createRouter, createWebHistory } from "vue-router"; +import DashboardView from "../views/DashboardView.vue"; + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: "/", + name: "dashboard", + component: DashboardView, + }, + { + path: "/mealplan", + name: "mealplan", + // route level code-splitting + // this generates a separate chunk (About.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => import("../views/MealplanView.vue"), + }, + { + path: "/chores", + name: "chores", + // route level code-splitting + // this generates a separate chunk (About.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => import("../views/ChoresView.vue"), + }, + { + path: "/settings", + name: "settings", + component: () => import("../views/SettingsView.vue"), + }, + ], +}); + +export default router; diff --git a/chorechef_frontend/src/views/ChoresView.vue b/chorechef_frontend/src/views/ChoresView.vue new file mode 100644 index 0000000000000000000000000000000000000000..9f235d8d13f5812b7d8e5cfcf99fd439cbd7a301 --- /dev/null +++ b/chorechef_frontend/src/views/ChoresView.vue @@ -0,0 +1,7 @@ +<script setup lang="ts"> +import Chores from "../components/Chores.vue"; +</script> + +<template> + <Chores /> +</template> diff --git a/chorechef_frontend/src/views/DashboardView.vue b/chorechef_frontend/src/views/DashboardView.vue new file mode 100644 index 0000000000000000000000000000000000000000..e3b9e5b4250617c39d920ed19107c713a166316a --- /dev/null +++ b/chorechef_frontend/src/views/DashboardView.vue @@ -0,0 +1,67 @@ +<script setup lang="ts"> +import Mealplan from "../components/Mealplan.vue"; +import Chores from "../components/Chores.vue"; +import { add, format } from "date-fns"; +import { onMounted } from "vue"; +import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; +import { + faCircleChevronLeft, + faCircleChevronRight, +} from "@fortawesome/free-solid-svg-icons"; +</script> +<template> + <div class="flex flex-col grow"> + <div + id="date" + class="flex justify-center m-6 p-4 rounded-xl bg-neutral-300 shadow-lg" + > + <FontAwesomeIcon + :icon="faCircleChevronLeft" + class="self-center h-8 w-8 ml-4 hover:cursor-pointer hover:drop-shadow-lg hover:scale-110 hover:text-primary-600 transition" + @click="decrementDate" + /> + + <p class="grow flex justify-center text-3xl font-semibold"> + {{ formattedDate }} + </p> + + <FontAwesomeIcon + :icon="faCircleChevronRight" + class="self-center h-8 w-8 mr-4 hover:cursor-pointer hover:drop-shadow-lg hover:scale-110 hover:text-primary-600 transition" + @click="incrementDate" + /> + </div> + <div id="content" class="flex grow px-4 gap-4"> + <div id="meals-section" class="flex flex-col w-1/2"> + <Mealplan :onDashboard="true" :currDate="currDate" /> + </div> + <div id="tasks-section" class="flex flex-col w-1/2"> + <Chores :onDashboard="true" :currDate="currDate" /> + </div> + </div> + </div> +</template> + +<script lang="ts"> +export default { + data() { + return { + currDate: new Date(), + }; + }, + name: "DashboardView", + methods: { + incrementDate() { + this.currDate = add(this.currDate, { days: 1 }); + }, + decrementDate() { + this.currDate = add(this.currDate, { days: -1 }); + }, + }, + computed: { + formattedDate() { + return format(this.currDate, "cccc d. MMMM yyyy"); + }, + }, +}; +</script> diff --git a/chorechef_frontend/src/views/MealplanView.vue b/chorechef_frontend/src/views/MealplanView.vue new file mode 100644 index 0000000000000000000000000000000000000000..fb9c0b39038f33f6a3dbb5c9a2da4aec45a996a1 --- /dev/null +++ b/chorechef_frontend/src/views/MealplanView.vue @@ -0,0 +1,7 @@ +<script setup lang="ts"> +import Mealplan from "../components/Mealplan.vue"; +</script> + +<template> + <Mealplan :currDate="new Date()" /> +</template> diff --git a/chorechef_frontend/src/views/MealplanView.vue.old b/chorechef_frontend/src/views/MealplanView.vue.old new file mode 100644 index 0000000000000000000000000000000000000000..f09ffc1a9b0405ff57d79e5e257bdb25d2864d02 --- /dev/null +++ b/chorechef_frontend/src/views/MealplanView.vue.old @@ -0,0 +1,198 @@ +<script setup lang="ts"> +import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; +import { + faPenToSquare, + faTimes, + faSave, +} from "@fortawesome/free-solid-svg-icons"; +import { ref } from "vue"; +import moment from "moment"; +import de from "moment/locale/de"; +moment.locale("de", de); +</script> + +<template> + <div id="meals" class="flex flex-row grow gap-1 p-1"> + <div + class="meal flex flex-col gap-1 w-1/4 border border-black rounded p-1" + v-for="n in 7" + > + <div class="flex flex-row"> + <div class="meal-date text-xl font-bold flex justify-center"> + {{ + today() + .add(n - 1, "days") + .format("DD.MM.") + }} + </div> + <div + class="flex justify-end w-full p-1 gap-2 flex-row" + v-if="editingMeal && editingMeal.meal_date === dateOnPos(n)" + > + <FontAwesomeIcon + :icon="faSave" + @click="saveMeal" + class="hover:cursor-pointer" + /> + <FontAwesomeIcon + :icon="faTimes" + @click="cancelEditing" + class="hover:cursor-pointer" + /> + </div> + <div v-else class="edit-button flex justify-end w-full p-1"> + <FontAwesomeIcon + :icon="faPenToSquare" + @click="startEditing(n)" + class="hover:cursor-pointer" + /> + </div> + </div> + <input + v-if="editingMeal && editingMeal.meal_date === dateOnPos(n)" + v-model="editingMeal.meal_name" + class="meal-name-input p-2 h-2/6 w-full flex flex-row gap-1 bg-gray-50 border border-black rounded" + /> + <div + v-else + class="meal-name h-2/6 text-xl font-bold border border-black rounded flex flex-col justify-center items-center" + > + {{ + meals.find( + (meal) => + meal.meal_date === + today() + .add(n - 1, "days") + .format("YYYY-MM-DD"), + )?.meal_name + }} + </div> + <textarea + v-model="editingMeal.meal_description" + v-if="editingMeal && editingMeal.meal_date === dateOnPos(n)" + class="meal-description-input p-2 h-4/6 flex flex-row gap-1 bg-gray-50 border border-black rounded" + ></textarea> + + <div + v-else + class="meal-notice text-sm break-normal h-4/6 border border-black rounded p-0.5" + > + {{ + meals.find( + (meal) => + meal.meal_date === + today() + .add(n - 1, "days") + .format("YYYY-MM-DD"), + )?.meal_description + }} + </div> + </div> + </div> +</template> + +<script lang="ts"> +import moment from "moment"; + +interface Meal { + meal_name: string; + meal_description: string; + meal_date: string; + meal_image: string | null; +} + +export default { + data() { + return { + meals: [] as Meal[], + editingMeal: null as Meal | null, + rollBackMeal: null as Meal | null, + }; + }, + methods: { + today() { + return moment(); + }, + mealOnPos(n: int) { + const date = this.today() + .add(n - 1, "days") + .format("YYYY-MM-DD"); + + return ( + this.meals.find((meal) => meal.meal_date === date) || { + meal_name: "", + meal_description: "", + meal_date: date, + meal_image: null, + } + ); + }, + dateOnPos(n: int) { + return this.today() + .add(n - 1, "days") + .format("YYYY-MM-DD"); + }, + + async fetchMeals() { + const response = await fetch("http://localhost:8000/meals"); + const data = await response.json(); + return data as Meal[]; + }, + startEditing(n: int) { + this.editingMeal = this.mealOnPos(n); + this.rollBackMeal = { ...this.editingMeal }; + }, + async saveMeal() { + const index = this.meals.findIndex( + (meal) => meal.meal_date === this.editingMeal!.meal_date, + ); + if (index !== -1) { + this.meals.splice(index, 1, this.editingMeal!); + } + + //Update the meal or create a new one in database + console.log(JSON.stringify(this.editingMeal)); + + if (index === -1) { + let resp = await fetch("http://localhost:8000/meals/", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(this.editingMeal), + }); + console.log(resp); + console.log(resp.json()); + } else { + fetch(`http://localhost:8000/meals/${this.editingMeal!.meal_date}/`, { + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(this.editingMeal), + }); + } + + this.meals = await this.fetchMeals(); + + this.editingMeal = null; + this.rollBackMeal = null; + }, + cancelEditing() { + console.log(this.rollBackMeal); + const index = this.meals.findIndex( + (meal) => meal.meal_date === this.editingMeal!.meal_date, + ); + if (index !== -1) { + this.meals.splice(index, 1, this.rollBackMeal!); + } + this.editingMeal = null; + this.rollBackMeal = null; + }, + }, + async mounted() { + const meals = await this.fetchMeals(); + this.meals = meals; + }, +}; +</script> diff --git a/chorechef_frontend/src/views/SettingsView.vue b/chorechef_frontend/src/views/SettingsView.vue new file mode 100644 index 0000000000000000000000000000000000000000..fe7a6fbd6bc682edc08099eb0f913e2afa0d5413 --- /dev/null +++ b/chorechef_frontend/src/views/SettingsView.vue @@ -0,0 +1,7 @@ +<script setup lang="ts"> +import Settings from "../components/Settings.vue"; +</script> + +<template> + <Settings /> +</template> diff --git a/chorechef_frontend/tailwind.config.js b/chorechef_frontend/tailwind.config.js new file mode 100644 index 0000000000000000000000000000000000000000..74038db35576ff17c166e798f70f70e55ca28d29 --- /dev/null +++ b/chorechef_frontend/tailwind.config.js @@ -0,0 +1,20 @@ +/** @type {import('tailwindcss').Config} */ +const defaultTheme = require("tailwindcss/defaultTheme"); +const colors = require("tailwindcss/colors"); + +export default { + content: ["./index.html", "./src/**/*.{vue,js,ts,jsx,tsx}"], + theme: { + extend: { + fontFamily: { + sans: ["Inter var", ...defaultTheme.fontFamily.sans], + }, + colors: { + primary: colors.indigo, + secondary: colors.red, + neutral: colors.gray, + }, + }, + }, + plugins: [require("@tailwindcss/forms")], +}; diff --git a/chorechef_frontend/tsconfig.app.json b/chorechef_frontend/tsconfig.app.json new file mode 100644 index 0000000000000000000000000000000000000000..e14c754d3ae5775d2ab13001e251c1371be912de --- /dev/null +++ b/chorechef_frontend/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/chorechef_frontend/tsconfig.json b/chorechef_frontend/tsconfig.json new file mode 100644 index 0000000000000000000000000000000000000000..66b5e5703e83c352671ce094731e9e861ada6924 --- /dev/null +++ b/chorechef_frontend/tsconfig.json @@ -0,0 +1,11 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + } + ] +} diff --git a/chorechef_frontend/tsconfig.node.json b/chorechef_frontend/tsconfig.node.json new file mode 100644 index 0000000000000000000000000000000000000000..f0940630302f8c4b03a6f601a908d6fa0240ad54 --- /dev/null +++ b/chorechef_frontend/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/chorechef_frontend/vite.config.ts b/chorechef_frontend/vite.config.ts new file mode 100644 index 0000000000000000000000000000000000000000..5c45e1d9b4e65e3a35bb0435436935a3090b5591 --- /dev/null +++ b/chorechef_frontend/vite.config.ts @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/startapp.sh b/startapp.sh new file mode 100755 index 0000000000000000000000000000000000000000..38dd433aee6e7f633465b4570e59c71bb9141ab0 --- /dev/null +++ b/startapp.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +# Setup Backend +cd chorechef_backend +python -m venv .venv +source .venv/bin/activate +pip install -r requirements.txt +python manage.py migrate +cd .. + +# Setup Frontend +cd chorechef_frontend +npm install +cd .. + +# Start Application + +python chorechef_backend/manage.py runserver & npm run dev --prefix chorechef_frontend/ + + +