From de5a7974d65aa0910c2ea7ffc7b0a2e339451a3b Mon Sep 17 00:00:00 2001 From: DanielAtonge Date: Sun, 2 Jul 2023 13:30:17 +0300 Subject: [PATCH 1/6] fastapi setup --- Backend/Dockerfile | 29 --- Backend/README.md | 115 ---------- Backend/__pycache__/main.cpython-39.pyc | Bin 0 -> 357 bytes Backend/alumni_portal/__init__.py | 0 Backend/alumni_portal/asgi.py | 16 -- Backend/alumni_portal/settings.py | 146 ------------- Backend/alumni_portal/urls.py | 24 --- Backend/alumni_portal/wsgi.py | 16 -- Backend/api/__init__.py | 0 Backend/api/admin.py | 6 - Backend/api/apps.py | 6 - Backend/api/models.py | 38 ---- Backend/api/serializers.py | 52 ----- Backend/api/tests.py | 3 - Backend/api/urls.py | 22 -- Backend/api/validator.py | 46 ---- Backend/api/views.py | 269 ------------------------ Backend/app/api/auth.py | 80 +++++++ Backend/app/main.py | 49 +++++ Backend/app/version.py | 16 ++ Backend/db.sqlite3 | Bin 192512 -> 0 bytes Backend/manage.py | 24 --- Backend/requirements.txt | 31 ++- 23 files changed, 171 insertions(+), 817 deletions(-) delete mode 100644 Backend/Dockerfile delete mode 100644 Backend/README.md create mode 100644 Backend/__pycache__/main.cpython-39.pyc delete mode 100644 Backend/alumni_portal/__init__.py delete mode 100644 Backend/alumni_portal/asgi.py delete mode 100644 Backend/alumni_portal/settings.py delete mode 100644 Backend/alumni_portal/urls.py delete mode 100644 Backend/alumni_portal/wsgi.py delete mode 100644 Backend/api/__init__.py delete mode 100644 Backend/api/admin.py delete mode 100644 Backend/api/apps.py delete mode 100644 Backend/api/models.py delete mode 100644 Backend/api/serializers.py delete mode 100644 Backend/api/tests.py delete mode 100644 Backend/api/urls.py delete mode 100644 Backend/api/validator.py delete mode 100644 Backend/api/views.py create mode 100644 Backend/app/api/auth.py create mode 100644 Backend/app/main.py create mode 100644 Backend/app/version.py delete mode 100644 Backend/db.sqlite3 delete mode 100644 Backend/manage.py diff --git a/Backend/Dockerfile b/Backend/Dockerfile deleted file mode 100644 index 5f58ee1..0000000 --- a/Backend/Dockerfile +++ /dev/null @@ -1,29 +0,0 @@ -FROM python:3.10 -# setup environment variable -ENV DockerHOME=/home/app/webapp - -# set work directory -RUN mkdir -p $DockerHOME - -# where your code lives -WORKDIR $DockerHOME - -# set environment variables -ENV PYTHONDONTWRITEBYTECODE 1 -ENV PYTHONUNBUFFERED 1 - -# install dependencies -RUN pip install --upgrade pip - -COPY requirements.txt $DockerHOME - -# run this command to install all dependencies -RUN pip install -r requirements.txt - -# copy whole project to your docker home directory. -COPY . $DockerHOME -RUN python manage.py migrate -# port where the Django app runs -EXPOSE 8000 -# start server -CMD python manage.py runserver 0.0.0.0:8000 diff --git a/Backend/README.md b/Backend/README.md deleted file mode 100644 index 12ea4ff..0000000 --- a/Backend/README.md +++ /dev/null @@ -1,115 +0,0 @@ -# Alumni Portal Backend - -## How to run - -### Using Python -1. Open a shell/command line in this folder (better if it was after activating a python virtual env) -2. Then run the following commands -```bash - pip install -r requirements.txt - python manage.py runserver -``` -### Using docker -1. Here the image tag name is `alumni-backend` you can name it as you like -2. Also the port in docker is 8000 by default and locally you can map it to anything as you like - -```bash -docker build -t alumni-backend -docker run -p 8000:8000 -d alumni-backend -``` - - -## API Explaination - -### Registration -``` -POST http://localhost:8000/register -Body: -{ - "email": "", - "password": "", - "password2": "" -} -``` - -### Getting Token - -* username should have value of email -``` -POST http://localhost:8000/api-token-auth -Body: -{ - "username": "", - "password": "" -} -``` - -### Ordering Pass -``` -POST http://localhost:8000/pass/ -Include in HTTP headers Authorization with value: TOKEN -Body: -{ - "date": "DD/MM/YY", - "invited_guests": ["", "", ... , ""] -} -``` - -### Get Elective Courses (non-booked) -``` -GET http://localhost:8000/courses -Include in HTTP headers Authorization with value: TOKEN -``` - -### Get Booked Elective Courses -``` -GET http://localhost:8000/courses/booked -Include in HTTP headers Authorization with value: TOKEN -``` - - -### Verify Email -* the code would be received on Innopolis email -``` -POST http://localhost:8000/confirm/email -Include in HTTP headers Authorization with value: TOKEN -Body: -{ - "code": -} -``` - -### Update Alumni Profile -* In body you can put any subset of attributes which you want to update -``` -POST http://localhost:8000/update -Include in HTTP headers Authorization with value: TOKEN -Body: -{ - "name": , - "name_russian" = , - "telegram" = , - "graduation_year" = , - "field_of_study" = , - "bio" = , - "city" = , - "company" = , - "position" = -} -``` - -### Get Alumni Profile -``` -GET http://localhost:8000/accounts/profile/ -Include in HTTP headers Authorization with value: TOKEN -``` - -### Request Elective Course -``` -POST http://localhost:8000/request/course -Include in HTTP headers Authorization with value: TOKEN -Body: -{ - "id": -} -``` \ No newline at end of file diff --git a/Backend/__pycache__/main.cpython-39.pyc b/Backend/__pycache__/main.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..318e39647746a3f09087aa546ff4bf74122b502a GIT binary patch literal 357 zcmYjLOG*SW6wFKdhdKvv=h9xxW}de~2WB1Wh`q0EmJWsi>lFOwxCd zOeQa61yv%`8&YOJcuh(e^Go5w>Ee0~ypGm3D2gu}Um!`4v;mB=`IvXgd$Cl{yH`qU zdvIr+mLJ5Wc(^t=#&YbKU&xF#uz&ldgx3u?X3$!^D|Mm z%1A!LSYu}W)0jAGLl%3)LWH^;d0wVf{(#*@-?-?HO!WQ8mMZ-1H#Po$F+UbZot1-D N$AHR5Yma8EfM52~PNV<; literal 0 HcmV?d00001 diff --git a/Backend/alumni_portal/__init__.py b/Backend/alumni_portal/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/Backend/alumni_portal/asgi.py b/Backend/alumni_portal/asgi.py deleted file mode 100644 index c4b1eae..0000000 --- a/Backend/alumni_portal/asgi.py +++ /dev/null @@ -1,16 +0,0 @@ -""" -ASGI config for alumni_portal 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/4.1/howto/deployment/asgi/ -""" - -import os - -from django.core.asgi import get_asgi_application - -os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'alumni_portal.settings') - -application = get_asgi_application() diff --git a/Backend/alumni_portal/settings.py b/Backend/alumni_portal/settings.py deleted file mode 100644 index 911985d..0000000 --- a/Backend/alumni_portal/settings.py +++ /dev/null @@ -1,146 +0,0 @@ -""" -Django settings for alumni_portal project. - -Generated by 'django-admin startproject' using Django 4.1.7. - -For more information on this file, see -https://docs.djangoproject.com/en/4.1/topics/settings/ - -For the full list of settings and their values, see -https://docs.djangoproject.com/en/4.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/4.1/howto/deployment/checklist/ - -# TODO replace this key with a secret one on releasing/production version -SECRET_KEY = 'django-insecure-j!x*&4_(-r&v9f-xr-lp7iq=ve+ak-bqzb5z6*pr=ffzxnlegg' - -# SECURITY WARNING: don't run with debug turned on in production! -DEBUG = True - -ALLOWED_HOSTS = ['ziadxkabakibi.fvds.ru', 'localhost', '127.0.01', '188.120.255.101'] - -CSRF_COOKIE_SAMESITE = "Lax" -SESSION_COOKIE_SAMESITE = "Lax" -# CORS_ALLOWED_ORIGINS = ['*'] - # set this -CORS_ALLOW_ALL_ORIGINS= False -CORS_ALLOWED_ORIGINS = ['http://127.0.0.1:3000', 'http://localhost:8000', 'http://localhost', 'http://localhost:3000', 'http://127.0.0.1:8000' , 'http://ziadxkabakibi.fvds.ru'] -CORS_ALLOW_CREDENTIALS = True -CSRF_COOKIE_HTTPONLY = True -SESSION_COOKIE_HTTPONLY = True -CORS_EXPOSE_HEADERS = ["Content-Type", "X-CSRFToken"] -CSRF_TRUSTED_ORIGINS = ['http://127.0.0.1:3000', 'http://localhost:8000', 'http://localhost', 'http://localhost:3000', 'http://127.0.0.1:8000', 'http://ziadxkabakibi.fvds.ru'] -# CORS_ALLOW_PRIVATE_NETWORK = True - -# Application definition - -INSTALLED_APPS = [ - 'django.contrib.admin', - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.messages', - 'django.contrib.staticfiles', - 'api.apps.ApiConfig', - 'rest_framework', - 'knox', - 'rest_framework.authtoken', - 'corsheaders', -] - -MIDDLEWARE = [ - 'corsheaders.middleware.CorsMiddleware', - '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', - 'django.middleware.common.CommonMiddleware', -] - -ROOT_URLCONF = 'alumni_portal.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 = 'alumni_portal.wsgi.application' - - -# Database -# https://docs.djangoproject.com/en/4.1/ref/settings/#databases - -DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': BASE_DIR / 'db.sqlite3', - } -} - - -# Password validation -# https://docs.djangoproject.com/en/4.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/4.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/4.1/howto/static-files/ - -STATIC_URL = 'static/' - -# Default primary key field type -# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field - -DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' - -TELEGRAM_TOKEN = "6125230376:AAGi7qfothkdpDGwwy7nB9x8VieXwzN9yNQ" -CHAT_ID = -1001525464247 -EMAIL_PASSWORD = "fkCySytmUKS2t5" diff --git a/Backend/alumni_portal/urls.py b/Backend/alumni_portal/urls.py deleted file mode 100644 index 59c08a2..0000000 --- a/Backend/alumni_portal/urls.py +++ /dev/null @@ -1,24 +0,0 @@ -"""alumni_portal URL Configuration - -The `urlpatterns` list routes URLs to views. For more information please see: - https://docs.djangoproject.com/en/4.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 path, include -from rest_framework.authtoken import views - -urlpatterns = [ - path('admin/', admin.site.urls), - path('', include('api.urls')), - path('api-token-auth', views.obtain_auth_token), -] \ No newline at end of file diff --git a/Backend/alumni_portal/wsgi.py b/Backend/alumni_portal/wsgi.py deleted file mode 100644 index 61d9f91..0000000 --- a/Backend/alumni_portal/wsgi.py +++ /dev/null @@ -1,16 +0,0 @@ -""" -WSGI config for alumni_portal 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/4.1/howto/deployment/wsgi/ -""" - -import os - -from django.core.wsgi import get_wsgi_application - -os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'alumni_portal.settings') - -application = get_wsgi_application() diff --git a/Backend/api/__init__.py b/Backend/api/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/Backend/api/admin.py b/Backend/api/admin.py deleted file mode 100644 index 7fec252..0000000 --- a/Backend/api/admin.py +++ /dev/null @@ -1,6 +0,0 @@ -from django.contrib import admin -from .models import Alumni, ElectiveCourse, ElectiveCourseRequest - -admin.site.register(Alumni) -admin.site.register(ElectiveCourse) -admin.site.register(ElectiveCourseRequest) \ No newline at end of file diff --git a/Backend/api/apps.py b/Backend/api/apps.py deleted file mode 100644 index 66656fd..0000000 --- a/Backend/api/apps.py +++ /dev/null @@ -1,6 +0,0 @@ -from django.apps import AppConfig - - -class ApiConfig(AppConfig): - default_auto_field = 'django.db.models.BigAutoField' - name = 'api' diff --git a/Backend/api/models.py b/Backend/api/models.py deleted file mode 100644 index e9f0b5a..0000000 --- a/Backend/api/models.py +++ /dev/null @@ -1,38 +0,0 @@ -from django.db import models -from django.contrib.auth.models import User -from django.contrib.auth.models import AbstractBaseUser - -class Alumni(User): - name = models.CharField(max_length=60) - name_russian = models.CharField(max_length=60) - graduation_year = models.IntegerField(default=1900) - filed_of_study = models.CharField(max_length=60) - bio = models.TextField() - city = models.CharField(max_length=60) - company = models.CharField(max_length=60) - position = models.CharField(max_length=60) - telegram = models.CharField(max_length=60) - verified = models.BooleanField(default=False) - - def __str__(self): - return self.name - - -class ElectiveCourse(models.Model): - name = models.CharField(max_length=100) - description = models.TextField() - tutor = models.CharField(max_length=100) - available_places = models.IntegerField() - - -class EmailCode(models.Model): - email = models.EmailField() - code = models.IntegerField() - - -class ElectiveCourseRequest(models.Model): - alumni = models.ForeignKey(Alumni, on_delete=models.CASCADE) - course = models.ForeignKey(ElectiveCourse, on_delete=models.CASCADE) - alumni_name = models.CharField(max_length=60) - course_name = models.CharField(max_length=60) - approved = models.BooleanField(default=False) \ No newline at end of file diff --git a/Backend/api/serializers.py b/Backend/api/serializers.py deleted file mode 100644 index 937ec98..0000000 --- a/Backend/api/serializers.py +++ /dev/null @@ -1,52 +0,0 @@ -from rest_framework import serializers -from django.contrib.auth.models import User -from rest_framework.response import Response -from rest_framework import status -from rest_framework.validators import UniqueValidator -from django.contrib.auth.password_validation import validate_password - -from .models import Alumni, ElectiveCourse -from .validator import validate_innopolis_mail - -class AlumniSerializer(serializers.ModelSerializer): - class Meta: - model = Alumni - fields = ['email', 'name', 'name_russian', 'telegram', 'graduation_year', 'filed_of_study', 'bio', 'city', 'company', 'position'] - - -class ElectiveCourseSerializer(serializers.ModelSerializer): - class Meta: - model = ElectiveCourse - fields = ['id', 'name', 'description', 'tutor', 'available_places'] - - -class RegisterSerializer(serializers.ModelSerializer): - email = serializers.EmailField( - required=True, - validators=[UniqueValidator(queryset=User.objects.all(), message='User with this email already exists')] - ) - password = serializers.CharField( - write_only=True, required=True, validators=[validate_password]) - password2 = serializers.CharField(write_only=True, required=True) - - class Meta: - model = Alumni - fields = ('email', 'password', 'password2') - - def validate(self, attrs): - if attrs['password'] != attrs['password2']: - raise serializers.ValidationError( - {"password": "Password fields didn't match."}) - if validate_innopolis_mail(attrs['email']) == -1: - raise serializers.ValidationError( - {"email": "Given email is not an official Innopolis University email address."}) - return attrs - - def create(self, validated_data): - alumni = Alumni.objects.create( - email=validated_data['email'], - username=validated_data['email'], - ) - alumni.set_password(validated_data['password']) - alumni.save() - return alumni diff --git a/Backend/api/tests.py b/Backend/api/tests.py deleted file mode 100644 index 7ce503c..0000000 --- a/Backend/api/tests.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.test import TestCase - -# Create your tests here. diff --git a/Backend/api/urls.py b/Backend/api/urls.py deleted file mode 100644 index 43c2b6f..0000000 --- a/Backend/api/urls.py +++ /dev/null @@ -1,22 +0,0 @@ -from django.urls import include, path -from rest_framework import routers -from . import views -from .views import AlumniDetailAPI, RegisterAlumniAPIView, PassOrderAPI, ElectiveCourseDetailAPI, VerifyMailAPI, UpdateProfileAPI, RequestCourseAPI, BookedCoursesDetailAPI - -router = routers.DefaultRouter() -router.register(r'alumni', views.AlumniViewSet) - -# Wire up our API using automatic URL routing. -# Additionally, we include login URLs for the browsable API. -urlpatterns = [ - path('', include(router.urls)), - path('api-auth/', include('rest_framework.urls', namespace='rest_framework')), - path("accounts/profile/", AlumniDetailAPI.as_view()), - path('register', RegisterAlumniAPIView.as_view()), - path('pass/', PassOrderAPI.as_view()), - path('courses/', ElectiveCourseDetailAPI.as_view()), - path('courses/booked', BookedCoursesDetailAPI.as_view()), - path('confirm/email', VerifyMailAPI.as_view()), - path('update', UpdateProfileAPI.as_view()), - path('request/course', RequestCourseAPI.as_view()) -] \ No newline at end of file diff --git a/Backend/api/validator.py b/Backend/api/validator.py deleted file mode 100644 index 443771e..0000000 --- a/Backend/api/validator.py +++ /dev/null @@ -1,46 +0,0 @@ -import smtplib, ssl -import random -from django.conf import settings -from .models import EmailCode - -CODE_MIN = 1000000000 -CODE_MAX = 9999999999 - -def send_confirmation_mail(receiver_email): - port = 587 # For starttls - smtp_server = "smtp.university.innopolis.ru" - sender_email = "alumni.portal@innopolis.university" - password = settings.EMAIL_PASSWORD - code = random.randint(CODE_MIN, CODE_MAX) - - message = """Subject: Alumni Portal Registration - - - Welcome to Alumni Portal! Your activation code is: {code} - - ___________________ - Regards, - Alumni Portal Team - """.format(code=code) - - smtp = smtplib.SMTP(smtp_server, port=port) - - smtp.ehlo() # send the extended hello to our server - smtp.starttls() # tell server we want to communicate with TLS encryption - - smtp.login(sender_email, password) # login to our email server - - smtp.sendmail(sender_email, receiver_email, - message) - - smtp.quit() - verification = EmailCode.objects.create(email=receiver_email, code=code) - verification.save() - return code - - -def validate_innopolis_mail(mail): - domain = mail[mail.find('@')+1:] - if domain == 'innopolis.university' or domain == 'innopolis.ru': - return send_confirmation_mail(mail) - return -1 \ No newline at end of file diff --git a/Backend/api/views.py b/Backend/api/views.py deleted file mode 100644 index a57d2ed..0000000 --- a/Backend/api/views.py +++ /dev/null @@ -1,269 +0,0 @@ -from django.shortcuts import redirect -from rest_framework import viewsets -from rest_framework.permissions import AllowAny -from rest_framework.views import APIView -from rest_framework.response import Response -from .serializers import RegisterSerializer -from rest_framework.authentication import SessionAuthentication, TokenAuthentication -from rest_framework import generics -from knox.views import LoginView as KnoxLoginView -import urllib -from .serializers import AlumniSerializer, ElectiveCourseSerializer -from .models import Alumni, ElectiveCourse, EmailCode, ElectiveCourseRequest -from django.conf import settings -from datetime import datetime -import smtplib, ssl - - -class AlumniDetailAPI(APIView): - authentication_classes = (TokenAuthentication,) - permission_classes = (AllowAny,) - http_method_names = ['get', 'head', 'post'] - - def get(self, request): - alumni = Alumni.objects.get(user_ptr_id=request.user.id) - serializer = AlumniSerializer(alumni) - return Response(serializer.data) - - def post(self, request): - self.http_method_names.append("GET") - alumni = Alumni.objects.get(user_ptr_id=request.user.id) - serializer = AlumniSerializer(alumni) - return Response(serializer.data) - - -class ElectiveCourseDetailAPI(APIView): - authentication_classes = (TokenAuthentication,) - permission_classes = (AllowAny,) - http_method_names = ['get', 'head', 'post'] - - def get(self, request): - # print(request.user.id) - alumni = Alumni.objects.get(user_ptr_id=request.user.id) - if alumni.verified == False: - return Response(status = 403, data={"status": "User needs to verify the email"}) - - courses = ElectiveCourse.objects.all() - data = [] - for course in courses: - exists = ElectiveCourseRequest.objects.filter(alumni=alumni, course=course).count() - if exists == 0: - serializer = ElectiveCourseSerializer(course) - data.append(serializer.data) - return Response(data) - - -class BookedCoursesDetailAPI(APIView): - authentication_classes = (TokenAuthentication,) - permission_classes = (AllowAny,) - http_method_names = ['get', 'head', 'post'] - - def get(self, request): - print(request.user.id) - alumni = Alumni.objects.get(user_ptr_id=request.user.id) - if alumni.verified == False: - return Response(status=403, data={"status": "User needs to verify the email"}) - - courses = ElectiveCourse.objects.all() - data = [] - for course in courses: - exists = ElectiveCourseRequest.objects.filter(alumni=alumni, course=course).count() - if exists > 0: - serializer = ElectiveCourseSerializer(course) - data.append(serializer.data) - return Response(data) - - -# Class based view to register user -class RegisterAlumniAPIView(generics.CreateAPIView): - permission_classes = (AllowAny,) - serializer_class = RegisterSerializer - - -class AlumniViewSet(viewsets.ModelViewSet): - queryset = Alumni.objects.all().order_by('email') - serializer_class = AlumniSerializer - - -def validate_date_format(requested_date): - date_format = "%d/%m/%y" - try: - return bool(datetime.strptime(requested_date, date_format)) - except ValueError: - return False - - -def send_pass_email(name, requested_date, invited_guests): - receiver_email = "n.novarlic@innopolis.ru" # this attribute has to be changed in future - - visitors = "\t1. {name}\n".format(name=name) - count = 1 - - for guest in invited_guests: - count += 1 - visitors += "\t{count}. {guest}\n".format(count=str(count), guest=guest) - - message = u"""Subject: Alumni Pass Order - - - Добрый день! - - Направляю на согласование список выпускников АНО ВО “Университета Иннополис” для посещения УЛК. - - Список посетителей: - -{visitors} - Дата посещения: {date} - Ответственные: (ФИО сотрудника УИ) - """.format(date=requested_date, visitors=visitors) - - port = 587 # For starttls - smtp_server = "smtp.university.innopolis.ru" - sender_email = "alumni.portal@innopolis.university" - password = settings.EMAIL_PASSWORD - - smtp = smtplib.SMTP(smtp_server, port=port) - - smtp.ehlo() - smtp.starttls() - - smtp.login(sender_email, password) - - smtp.sendmail(sender_email, receiver_email, - message.encode("utf-8")) - - smtp.quit() - - -class PassOrderAPI(APIView): - authentication_classes = (TokenAuthentication,) - permission_classes = (AllowAny,) - http_method_names = ['get', 'head', 'post'] - - def post(self, request): - alumni = Alumni.objects.get(user_ptr_id=request.user.id) - if alumni.verified == False: - return Response(status=403, data={"status": "User needs to verify the email"}) - - ''' - ### Might be useful later - message = f"{alumni.name} requested a pass." - url = f"https://api.telegram.org/bot{settings.TELEGRAM_TOKEN}/sendMessage?chat_id={settings.CHAT_ID}&text={message}".replace(" ", "%20") - urllib.request.urlopen(url) - ''' - requested_date = request.data['date'] - invited_guests = request.data['invited_guests'] - - if not validate_date_format(requested_date): - return Response(status=402, data={"status": "Wrong date format"}) - if alumni.name_russian == "": - return Response(status=402, data={"status": "There is no Russian version of name for current Alumni"}) - - send_pass_email(alumni.name_russian, requested_date, invited_guests) - - return Response({"status": "Pass Ordered"}) - - -class VerifyMailAPI(APIView): - authentication_classes = (TokenAuthentication,) - permission_classes = (AllowAny,) - http_method_names = ['get', 'head', 'post'] - - def post(self, request): - alumni = Alumni.objects.get(user_ptr_id=request.user.id) - code = EmailCode.objects.get(email=alumni.email).code - print(code) - if request.data['code'] == code: - alumni = Alumni.objects.filter(user_ptr_id=request.user.id).update( verified=True) - return Response({"status": "Successfuly Verified"}) - else: - return Response(status = 402, data={"status": "User failed to verify mail"}) - - -class UpdateProfileAPI(APIView): - authentication_classes = (TokenAuthentication,) - permission_classes = (AllowAny,) - http_method_names = ['get', 'head', 'post'] - - def post(self, request): - alumni = Alumni.objects.get(user_ptr_id=request.user.id) - if alumni.verified == False: - return Response(status = 403, data={"status": "User needs to verify the email"}) - try: - if request.data['name'] is not None: - alumni = Alumni.objects.filter(user_ptr_id=request.user.id).update(name=request.data['name']) - except: - pass - - try: - if request.data['name_russian'] is not None: - alumni = Alumni.objects.filter(user_ptr_id=request.user.id).update(name_russian=request.data['name_russian']) - except: - pass - - try: - if request.data['field_of_study'] is not None: - alumni = Alumni.objects.filter(user_ptr_id=request.user.id).update(filed_of_study=request.data['field_of_study']) - except: - pass - - try: - if request.data['graduation_year'] is not None: - alumni = Alumni.objects.filter(user_ptr_id=request.user.id).update(graduation_year=request.data['graduation_year']) - except: - pass - - try: - if request.data['bio'] is not None: - alumni = Alumni.objects.filter(user_ptr_id=request.user.id).update(bio=request.data['bio']) - except: - pass - - try: - if request.data['city'] is not None: - alumni = Alumni.objects.filter(user_ptr_id=request.user.id).update(city=request.data['city']) - except: - pass - - try: - if request.data['company'] is not None: - alumni = Alumni.objects.filter(user_ptr_id=request.user.id).update(company=request.data['company']) - except: - pass - - try: - if request.data['position'] is not None: - alumni = Alumni.objects.filter(user_ptr_id=request.user.id).update(position=request.data['position']) - except: - pass - - try: - if request.data['telegram'] is not None: - alumni = Alumni.objects.filter(user_ptr_id=request.user.id).update(telegram=request.data['telegram']) - except: - pass - - return Response({"status": "Attributes Updated"}) - - -class RequestCourseAPI(APIView): - authentication_classes = (TokenAuthentication,) - permission_classes = (AllowAny,) - http_method_names = ['get', 'head', 'post'] - - def post(self, request): - alumni = Alumni.objects.get(user_ptr_id=request.user.id) - if alumni.verified == False: - return Response(status = 403, data={"status": "User needs to verify the email"}) - course_id = request.data['id'] - course = ElectiveCourse.objects.get(id=course_id) - try: - course_request = ElectiveCourseRequest.objects.get(alumni=alumni, course=course) - return Response(status=403, data={"status": "Course already requested by user"}) - except: - pass - alumni_name = alumni.name - course_name = course.name - course_request = ElectiveCourseRequest.objects.create(alumni=alumni, course=course, alumni_name=alumni_name, course_name=course_name, approved=False) - course_request.save() - return Response({"status": "Successfuly requested course"}) \ No newline at end of file diff --git a/Backend/app/api/auth.py b/Backend/app/api/auth.py new file mode 100644 index 0000000..ec970e5 --- /dev/null +++ b/Backend/app/api/auth.py @@ -0,0 +1,80 @@ +from anyio import Path +from fastapi.security.oauth2 import OAuth2PasswordRequestForm +from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException, Response, UploadFile, status +from sqlalchemy.orm import Session + +from app.utils.oa2 import get_current_user +from ..schema import schemas, auth +from ..models import models +from ..database.configuration import get_db +from app.core import user +from ..utils import hash, token +# from app.services import storage + +router = APIRouter(tags=["Authentication"], prefix="/auth") + +@router.post("/login", response_model=auth.Token) +def login( + user_cred: OAuth2PasswordRequestForm = Depends(), + db: Session = Depends(get_db) +): + user: schemas.User = ( + db.query(models.User).filter(models.User.email == user_cred.username).first() + ) + + if not user: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, detail=f"Invalid Credentials" + ) + if not hash.verify_password(user_cred.password, user.password): + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, detail=f"Incorrect password" + ) + + access_token = token.create_access_token(data={"sub": user.email}) + + return {"access_token": access_token, "token_type": "bearer"} + + +@router.post("/signup", response_model=schemas.ShowUser, status_code=status.HTTP_201_CREATED) +def create_user_account(new_user: schemas.User, db: Session = Depends(get_db)): + return user.create(new_user, db) + + +@router.post("/forgot-password") +def forgot_password( + user_email: schemas.UserForgotPassword, + background_tasks: BackgroundTasks, + db: Session = Depends(get_db) +): + user.forgot_password(user_email.email, background_tasks, db) + return Response(status_code=status.HTTP_200_OK) + + +@router.post("/update-password") +def update_password( + user_info: schemas.UserUpdatePassword, + db: Session = Depends(get_db), +): + user.hash_update_password(user_info, db) + return Response(status_code=status.HTTP_200_OK) + + +@router.post("/verify-account") +def verify_account( + background_tasks: BackgroundTasks, + user_email: schemas.UserVerifyAccount, + db: Session = Depends(get_db), +): + user.verify_user_account(user_email.email, background_tasks, db) + return Response(status_code=status.HTTP_200_OK) + + +@router.post("/confirm_verification") +def confirm_verification( + verify: schemas.VerificationCode, + db: Session = Depends(get_db), +): + user.confirm_verification(verify.code, verify.email, db) + return Response(status_code=status.HTTP_200_OK) + diff --git a/Backend/app/main.py b/Backend/app/main.py new file mode 100644 index 0000000..69b3580 --- /dev/null +++ b/Backend/app/main.py @@ -0,0 +1,49 @@ +from fastapi import FastAPI +from starlette.responses import HTMLResponse +from fastapi.middleware.cors import CORSMiddleware +# import sys +# print(sys.executable) +# print(sys.path) + +from app.version import router as final_router + + +app = FastAPI( + title="AlumniPortalAPI", + description="Building a united community of Innopolis Alumni", + version="1.0", +) + +origins = ['*'] + +app.add_middleware( + CORSMiddleware, + allow_origins= origins, + allow_credentials= True, + allow_methods=["*"], + allow_headers=["*"], +) + +app.include_router(final_router, prefix="/api/v1") + +@app.get("/", response_class=HTMLResponse) +def index(): + return """ + + + + Alumni Portal | API Documentation + + + + +
+

AlumniPortalAPI

+ + +
+ + + """ \ No newline at end of file diff --git a/Backend/app/version.py b/Backend/app/version.py new file mode 100644 index 0000000..c0586a1 --- /dev/null +++ b/Backend/app/version.py @@ -0,0 +1,16 @@ +from fastapi import APIRouter +from app.api import transaction, user, auth, admin, file, country, landing + +router = APIRouter() + +def version_one(): + router.include_router(auth.router) + # router.include_router(user.router) + # router.include_router(country.router) + # router.include_router(transaction.router) + # router.include_router(landing.router) + # router.include_router(file.router) + # router.include_router(admin.router) + + +version_one() \ No newline at end of file diff --git a/Backend/db.sqlite3 b/Backend/db.sqlite3 deleted file mode 100644 index 453ae06c321573cd6202d7a63794c9324db8ed8e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 192512 zcmeI5dvF^`e%~pjf zF9HKf+|8v-Y4Fya|@FK<2s(h06i(2(!x_`f4fBVxt4fOPIaP8_P-Oz-^a%QT^-y8hwpfQ;6{)PA7df)J#_xcCEKJbqQE)4id z2)sZ51V8`;KmY`Oj09pMZpTnGrB?JvB%);0LcLhhGlo{sma1w|ib(QgBsv+138FMD z#ik?5loVHzqWlvA@k?2La)#LF41G<@mFv}-R@GMPTFo%Ml}SkvByn0+re$d=k%&pL z|8nW|PSuW1b#EK4orGsSXMYetg=F-Ag7i?OLhQYNb9gKo!x zu~bc~)%0?yMj9e!^pbAqYN6dpj7&?)l%hmqG3CSow_{H#wNfhIB@T&Z&2?khD6eRx zOieA=Ensz8?s76FD%1Ok`|*Z*Jfqf)az=`X$%rV5nMhQTdR8rq@uV`nuhlo!^o>Ol zVj>es%DsIhC8>zVpCi5}8udo0ucg;iy`ru6tXPyINhSF#aZWazNpCluwYwF)s?~bB zMwD12KK)FqX1S?38cB+=j2M+-y?o_lJfS3}L#@72r>`PKd-^7#@u+faFYz5~NZztv z<#;S2#o~M1j^T+^vuUJrLO-i@JF}^^OoBgW@z# zBFr`-L@X^!)pEVEEg51o5l@~Ak|5WuAdzHig9_?4+ar=$Ksg&AfvzI7Iea=T&-o)d_JR9tL18@NTwWhsrPv!CF8M}obr)iGmT&| zGR>^k$(fePl}muvVl?`i&GXGs(_~Yw7(FKdDWSxa_~`)>q0!gmlxk7Irtb#~IVqkLBhm97 z5~MMBBaOjpkG1WL8YwP|Qv7_s+c9=7)ryf)Y)s=;euna8L3<5iDHcme(HXbf5h9xM zMZLr(3&NB1Om&_0vr0bJ%B9R=L0!t^mdko>lg^IDqH;3jBB2OnE0mOJhH8AS(N767 ze0r*hMiLPv;v^x+bYO+pazc<4g|y&UA7N@vJ4F804zd!HlsHGwjdh~i+EGj-WHG@1 zyu-^s=ivXCPx4>p*Z9xyOZ-3OFOw|1KmY_l00ck)1V8`;KmY_l00cnbV?f|Q(0P(0 zm+*RD2k+nA=bYs7x7E@TUHy~m4D`Z)XK%nM_HgP8_?*KWy?)8A>h%w~ofGDveVs%J z3_3>!m<_wy#=qwX+L(9xo#STU#&va9$mNt93Rno_DwfcDjbhTAh?OR@(k&T*D)5xz6r6vTr={4Y`Ix9R-8C zTziH&dJ9_fb|vp#*HE~-zJZ`?=vkU=-k|5%?K-fJYuxZ={l9;|YwQr$dPhXddw0OK zXAi5M-tXZGy7ri2*yRJ~kZX@A+P=ilx6>6m;AK}U8h0_!iv@w;|8?+x%72sp8vhmk zZT@HY*U4W3T;)&jhxuKk2rm!-0T2KI5C8!X009sH0T2KI5O^X9><_pcL-Ebl|2zDo zbhvf>AM&{z!z0b*yuJS4HAo6V?FBo%F2|nXw)Ov>0TMCXRbRkEvY&0P|A+crjsyET z*8lt5F2~rRmNkE^<-OlUs@g-Vr|bWKlN>QIZ2iBhj~p`5_WFM(=W>J&w5|W?{=ee; zyAJ-lWY_;c@?YS8fq#=P@~`mcc!eL~cko>ByTNYKE&NFF3kB&8I6t5$X*vW$@v>qH?ohJ*^TNN*;7L< zZk+S8DjIo{dtBTE=VM{*b=1+2i#x{othjdmgqd#zw)0hf@X0--++Z`-7>n&?VVWzu!>ol~D^xT4keO|TYi5tKhLe5Py!|we zk!M|;%ng`4+kgxETwI(RXh3Z%8#c?V3flYn;4>~x~7W)w-vIbV8|@6!nPFbV#CNyL$~DaWL@cE;pvKa2NU43;?f-6%&`K}oM6z! z9pGFv5?e$w0!|i!Eu;O6fYXY>vV3Ni6@+CCvYMSV3On{PeSIv9z5E_v!@19jW#@a$ zd@G=x-_NM_(WrK&dzZ^Q&audiJ$%=0mv@4*!ZtFUEYphF$n4wU@{X~A*~p>$|IWaN zj^MBGSIGbH0s#;J0T2KI5C8!X009sH0T6il2yBS`0msG($H2+J$pLRFP|2?37o|*X zS(T!(!*Y^5c`kCebZ)g?si^6~;?n8DtBKnAmv6-L`r%h+vJ-dZ)cKcF%e70h*JtG$ zS0Z=sTuEKJtj%XHi&rl$T)IBDdg{WdD=R08Q)*#F&8jPUR)0w^mCBWJL9b0!>zfvs zkJ5`xig7^{r=!tnF+LS1PXbNGHx9a}=9D)S2zWQsTwJ)ZQmNfcEuGD+T_`T(@(YnG z*|Udhh1F{}mSzm&w0a>G%df;wFUE@V;^LxIPe)R>&)zNN0q5qB9VxT8hZwwO`%5C;`6b!xhtz{}uj!K7E56Edl`$009sH z0T2KI5C8!X009sHfhV270rG&tO|PN!d!6KI0QA9xu6@qq+$I+W$i)is+VP~5fPN4F z0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5cqf#p!@%QfuDEq z(fsFe$K`m^uCon_5f)~dvA zQM)57*Gu`TmKO?oNn@4d%6Uy#EYtE@QLP$6Ww~6^1hrBTSSEEU>V*Og)$Non8Ctbc z)oYqCuhq)+YEBcb6x32lFD(%Xrv52mVVN{yla}eMWkQZPlPHyHc}>p~X@-_tF6pav z`nD|OwKc6!t`MuzA}KDBYV?vo+9fndke1WKMx8=dqY_BCd_70nOWTrLt?RVyRq`kI z)qFv#F#x(z6KeWvq{*eckS~*`SC*zy6woDfZk*;kj@f&MCb?8Kx2zLw zMxFFaYad-(uNhjg_Mmb>)r+h}hNkA0h4pe>ST5f&n^@DAN=F6KL0YwD5H&}cByElS zW}s@2rkOPeszLGv)fS=_gaYNmdOuq;s${5;?s~bP=Jldp6|QMTjXXi%AnyPFF`U|{ z5(Gd11V8`;KmY_l00ck)1V8`;{)!1;{r^`C9MypU2!H?xfB*=900@8p2!H?xfWVJ| z0Db(+{_pXB zi+_vX;9uwKe3{qz9Dj>{g}=&Q<4hSqAX6Zqe9-ygbKTG$q z^f{J3OVj>mSQ=vKUY72mse3m|hgiCcr8{Zr+QCwur9qYkXzKK{)W_06mU?O0H^5R4 zOZ!>sb~(MAizZH*^f{egFZTaG>Y#%^2!H?xfB*=900@8p2!H?xfB*=Aj1OX5L0T2KI5C8!X009sH0T2Lzk3t~edEdcv?>P9w!T;j@ z?f!okxa0qs{@w0ZT>rrLL+{CfwC^XJzs|kG?RWf5$GeUb9X0v>tpCl9tcO1IywAP( z(9R!w$NPVMpC>dq$-Q;VP_qRse_Jgrl{0F-sFyN@@>1vV!PE2U)IwTVNS(Tr7DhXZ zM};G!dVW;UONO?jRfW0B3&Py>OP7Qz^E0!l`J2MU^i3gkec|%V90@d=o?AF7jFz*v zwVaWmeuj3}U=DV6RjX7-g*COBTUM(_q(~&(j7p5uoS~OXnZ<&-G%D1JYN0@?7V4#% zzEslkO-teQ`Sj_FL|mKwizkFgm;@n_OG{d&sMTuflGadRNvGvy(wvf!G1e;@li6$@ zZQ6YLYbubBAy-6RwNZU8p%a+nR-cIwH2D?LskQ>&&^!Do))^=v8|w;tuURa_C|-3zHjIu zEtuZv2`weL4b^UeS!y@6vnvuxE}Bb98q?opysJkybQyJYZX;rg_%4@T_$PLFLbr(c z*{#HzkqG>(C`EGF#bj^YJGZ5~E7*f1HylR8_aZ(v^}R8~roPVJ?>zQfdaS9hv)DQx zf3&HuF$B83KH53oY~(fqGh0jj17@kP?|H|SNBNPtac9p!Xv3T0?j5s741>aw)*)}9 z>KLe^qQ-<&9H1#Hf1t*vFCG55|G9jAC(Byye)?e>JOl9?*n z(QwuswU!ww9*riWiqbjW_VzeEn1sy&bm}$js7m&Z&7b$?20Wo;l6xa=pAu%NEx*Q; zbme+`oE}|94|S3>ExqF9fP0X%kvS>M@>`tWTbR?ITrD!%{&mdi{J1osT zz6W&K+9&Q7)wDFKD*$bpnMsCZ*BA}oyW#hQQYr3@J}_`a=^F+)W0ywp!2)EmPB0>sl$N zbsRd|5Ox$EDXB&6DDez$+~ho=W5>9ADvN2YmWujPRi(?8T31G2TinL-%653D9#Jcm zmIYKa+O~kAS~o8xt_58qQ)BnK0sH^m^Ez@s00ck)1V8`;KmY_l00ck)1VG?vBM|VM za`^gPj{bkx@8Xr99!U9DeE-208T`;Y=iTQy<@US2?)+tEq3=6=SGf5;pX1AY=N|zB zr}7AbIQrju6j2ZZ1V8`;KDGolb{uHk4C=fasJYXWi^dc!tHwGF_FI>`tvf3^i@W^I zeUnZzdQrTw>k!^JvfmTRko~EvY%i$OHq&}*4&DCADcPKs(6XI|`yL=|vpAbe?C=;3 zI~?3MKej{XX>Pa}=?|rcIR_ho*5(k|jw`d{jJ+`@Hs221f8m%XG(60G`cV6}Uem(U zzBAO!f2bXyidw7PDObt9PUF5hQA)IJ3l-FwLGS<5ORal9-u z<#M5UHyJ6Vx$T=uVzlL+J;B^WC5EhuEi8$NR#f$ZEmDdqZ6c`ojLC40yB=wnv!P@TL*3#?8EZyY{M?$?@VyI;%RHtm`#r9~wk(-d=0-?j_3PnE1a zcIl>3S~kILYueJTiE`uGAx~(1g1g7t`}?*_R|UCpUZaiAL_{?!$D^vfwQqa%TcUgH z>Dxxz4884^kkQo;M{YkG8}-or<~KNdK-g7xP(09MXxPRNH9k5qZ@r~%eLl82S+zcR z>%Q4$d%EekjkkTQO09d;;f?bnWQwHk3z>K@RCsgtGy zeJ&^G9l-kk@$XD11OX5L0T2KI5C8!X009sH0T2LzO$g8xzKgB@U2OgDV(WhwTmQS* z`rpOY|E>TDpm;v*;J?Lxf&UwPmY?SR!QTu1YVhZR)!eab1K;oZe%V*`9rq0kerNDk2j3d}$-$Qf_j~````^6(()+XC zocBdJ-<#W!V3gI00ck)1VF$d@RH(oaH-kAny%f+Xa$Wu^gLIt zSIJY@=}#BejMHjKprt~iR4|JLtNe^iBBZYd$a9l5@?`XeRaXqNeA6hB86~%@mX@}N zVwP_fdbqo-{GG>0@luT2~yhLdrBqtUIV zjfUFBQ>JmFZLP+Q_B4&hCW-O5=x0r6wPdoJW`~Xvvx%^eDK*L~TB%Yk-(7D?Wm)4B z#OTpBOO5T-zDg zl-oF|tWz&KOkCor0ZVhE)I8;=lO?=S&~Q6wx>@QQrM8>ZghqkocI*Ig6ORwjb~K7? zAKI8kuH|rWKXEuT?lIXH>cx`YYzh0#hkc}ce8ST}-n6h}Gn?m3n+EBojir&=?0=Tn zjEs30;HCi;#3DRHO2;PqnTncLtC1f}Z_2QapAQk6u-I=YX|b}TH0<`8c9xnJJ4=q0 zBkUn|hbH=|q81}6$vT|aO)MtkZl=n5aJ#WyvF8{oPoSB{hKR9v+-=G0Ft;SOIqWhW zES((=mey8>@J`||5p`3+9oAHItLgq7#B_Mv#gtRPO_=mR;7RGB36~|cQEq8u7D3a( z($=uBMA5_N0>t9Ln2U;O6jK%S{Xst|8wopE?d&%#n$?@XaN#56W0Ov+{-%W`z_b}O zZ7c;%8%qK^-tQ$g!{bh>p=m%xu!AE5q;x{=V=C;QPiRW9vyOU*<*|65rN=Iyww5S6 z^Ju?mZ7H)0sI?`}&V1fYtixg-)oABZQ!3QXIqY&fyyGGhOMZ$)D;ZV$1A=4-Ea!-m zSWQGNp{;h7Oxv=LSz01nEiH*n%TbP4jvb={Tg|AvrVU;Hdjel`@So>@D)_zNXM>*% z4v|B=KmY_l00ck)1V8`;KmY_l00bUe0_Qwl2S3XNI4-56tqWME*(Kz8^AfU9&fX?h zmW3lq*cot15lNnmD3elDkRsF3=yX(`N+y!=X#8A%GmyM>Ah}1N$h4wNMWW=_LKElQ z%|O!Dfuy!TiXcfu&a^B}B}GM+q!||rw39SV+&YjL?)${8md2T(#Azuqm6VmZ6fHSf zs84J!)a#?>nmRu^Exb;CQdBGCYvk=GMpG4Xp?8h^_UNroeX3V|Vr)u|#AETuTpy|L zq<4bU*TJCK9a8ucuaA;NIf+JUA@K(6&XFk!IXSJ!Q*k93Q6h6(GhPRZW<2qM@eS1S^0F$%%|Ow~NK6pPZ58C^iuhDKl8h@6H{Jj5>Cl*ojF-^T4%T^18 zJFhLStw~ebg}X1`o=soAqo=N(TAVyvTR)pRE0z;lJt3zr+&sHFUzxd9s;y_LwL|G$s_l7s&?N$>&z5C8!X009sH0T2KI5C8!X009tqtOy)( zxg00m#VNJ0qGr_R{FC#K8&pSmM(A0{aQ495ANw?n}J3XIHEu@8o)Tv8pVbm@d z6^@M7Yg#o^F{&9oKPu=YLtE0S!rbKrVea~+OTv};nc39*P2pntrZAsAo1Rb4olajP zG3v&0hPu)a#4{|Mp{4VzhMBpUg_+c)OE;~|^qHf=Xh|(_gi=H-=gO{dZ}t#VDP>WjKYAZN?vLTkN-R?tY>ioIRK8`BG(kam*WxTTl! z+Fjav#35(sYg(>cuaZ8{R_j{L$e2f@A2X_&)pFTfepA~iYedYEydIqpgqOJkmcKW5RFI=9PBN1oQa|>jsTSB)yudJTf(nhURs^zs_1Jg#) zt*mV_XwEsE6Uu|91$(RrS$&C|(akfXeZJ`$_1l|x!sO54{>}F1R#-l61U4owdqU&m z+`VV*bFirDg7 zt@F3l(o#87)5u2~`P|a(R`jZt$*YEzQKPw-6pP92CgJwUt-Y|Pzd5J18`1{1)HNDD zKHDF<9OfKMRBg4OQvr3O%#Jhd&Ka@&_{c`=k|z`nbN9wsAGDXYAC0&7LVF=q)gZB= zwS1N;E#C%O=R7jYHS7s8wfiHxwT%L$YUo9+IfH~Zf)_os*&8Bj=Sr!3m$rJ@D6eRx zjF}Q4nZ%;97|$#5c7wz1UD00H!`tkLb~D=KW4#r3R@i+!SrQo=sbIz~gTs*z46-=Vttnhcdj(;o0)^&@|CwfnF6^|eJIshEvIGMsHu z~J61D9N7C!~}PL$ecIZM}3F2(B4NKrL>c_ zd%8Yk2VI|=xq3a_{)zvi^;7tsQ}TpFk-IP29~5n0le@pA`8t}t*>{ZY0oA%J>ik~T z{$)#yw9IW}tmL&?uBuner9$Tl#2_;=S=TfcNu9px8u{R(i@Z#wpysq%kB=Yr{6GF3 z2mcQLw;#8Ua_9j85C8!X009sH0T2KI5C8!X0D-5M!0N=z0LRVgE9HVJ%vn44sghb) zujw_RyeM2NFB*5$swSkWhPJ5YjGD7A-tTct%noqgPCv4HN-o{zj5@Jz^}V)UGqhsO zZT|iL2M+!N{{5$yDOv^sAOHd&00JNY0w4eaAOHd&00JLR0zRkP$#L#}bN&CJga45K z!N-#XS`7jq00JNY0w4eaAOHd&00JNY0#7l4!9JJM%k`Vj|NESS{|f)Pr?|Cf8VG;@ z2!H?xfB*=900@8p2!H?xJTU}<{eDLv&=;Vufq Date: Mon, 10 Jul 2023 09:05:04 +0300 Subject: [PATCH 2/6] integrates backend and bot --- Frontend/requirements.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Frontend/requirements.txt diff --git a/Frontend/requirements.txt b/Frontend/requirements.txt new file mode 100644 index 0000000..efecf23 --- /dev/null +++ b/Frontend/requirements.txt @@ -0,0 +1,2 @@ +protobuf==4.21.12 +pywatchman==1.4.1 From 83bf428cb1a5b0e91053617461e669f31f336339 Mon Sep 17 00:00:00 2001 From: Daniel Atonge Date: Mon, 10 Jul 2023 09:08:14 +0300 Subject: [PATCH 3/6] integrates backend and bot --- .gitignore | 9 +- Backend/__pycache__/main.cpython-39.pyc | Bin 357 -> 0 bytes Backend/app/api/auth.py | 80 ------ Backend/app/api/elective_course_api.py | 39 +++ Backend/app/api/pass_request_api.py | 29 ++ Backend/app/api/user_api.py | 155 ++++++++++ Backend/app/config.py | 26 ++ Backend/app/db.py | 3 + Backend/app/main.py | 25 +- Backend/app/prisma/schema.prisma | 92 ++++++ Backend/app/schema/schemas.py | 192 +++++++++++++ Backend/app/telegram/admin/controller.py | 41 +++ Backend/app/telegram/admin/data.py | 25 ++ Backend/app/telegram/admin/handlers.py | 144 ++++++++++ Backend/app/telegram/controller.py | 263 +++++++++++++++++ Backend/app/telegram/core_handlers.py | 179 ++++++++++++ Backend/app/telegram/course_handlers.py | 149 ++++++++++ Backend/app/telegram/data.py | 161 +++++++++++ .../app/telegram/donation_profile_handlers.py | 130 +++++++++ Backend/app/telegram/init.py | 18 ++ Backend/app/telegram/request_pass_handlers.py | 266 ++++++++++++++++++ .../app/templates/account_verification.html | 180 ++++++++++++ Backend/app/templates/forgot_password.html | 182 ++++++++++++ Backend/app/utils/email_handler.py | 32 +++ Backend/app/utils/hash.py | 10 + Backend/app/utils/oa2.py | 18 ++ Backend/app/utils/token.py | 37 +++ Backend/app/version.py | 19 +- Backend/log | 1 + Backend/requirements.txt | 46 ++- 30 files changed, 2442 insertions(+), 109 deletions(-) delete mode 100644 Backend/__pycache__/main.cpython-39.pyc delete mode 100644 Backend/app/api/auth.py create mode 100644 Backend/app/api/elective_course_api.py create mode 100644 Backend/app/api/pass_request_api.py create mode 100644 Backend/app/api/user_api.py create mode 100644 Backend/app/config.py create mode 100644 Backend/app/db.py create mode 100644 Backend/app/prisma/schema.prisma create mode 100644 Backend/app/schema/schemas.py create mode 100644 Backend/app/telegram/admin/controller.py create mode 100644 Backend/app/telegram/admin/data.py create mode 100644 Backend/app/telegram/admin/handlers.py create mode 100644 Backend/app/telegram/controller.py create mode 100644 Backend/app/telegram/core_handlers.py create mode 100644 Backend/app/telegram/course_handlers.py create mode 100644 Backend/app/telegram/data.py create mode 100644 Backend/app/telegram/donation_profile_handlers.py create mode 100644 Backend/app/telegram/init.py create mode 100644 Backend/app/telegram/request_pass_handlers.py create mode 100644 Backend/app/templates/account_verification.html create mode 100644 Backend/app/templates/forgot_password.html create mode 100644 Backend/app/utils/email_handler.py create mode 100644 Backend/app/utils/hash.py create mode 100644 Backend/app/utils/oa2.py create mode 100644 Backend/app/utils/token.py create mode 100644 Backend/log diff --git a/.gitignore b/.gitignore index 54d21bc..1bb661e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ -Backend/api/__pycache__/ -Backend/alumni_portal/__pycache__/ -node_modules/ +Backend/**/__pycache__/ +Backend/**/.DS_Store/ +Frontend/node_modules/ +Backend/**/.env +Backend/venv +.DS_Store \ No newline at end of file diff --git a/Backend/__pycache__/main.cpython-39.pyc b/Backend/__pycache__/main.cpython-39.pyc deleted file mode 100644 index 318e39647746a3f09087aa546ff4bf74122b502a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 357 zcmYjLOG*SW6wFKdhdKvv=h9xxW}de~2WB1Wh`q0EmJWsi>lFOwxCd zOeQa61yv%`8&YOJcuh(e^Go5w>Ee0~ypGm3D2gu}Um!`4v;mB=`IvXgd$Cl{yH`qU zdvIr+mLJ5Wc(^t=#&YbKU&xF#uz&ldgx3u?X3$!^D|Mm z%1A!LSYu}W)0jAGLl%3)LWH^;d0wVf{(#*@-?-?HO!WQ8mMZ-1H#Po$F+UbZot1-D N$AHR5Yma8EfM52~PNV<; diff --git a/Backend/app/api/auth.py b/Backend/app/api/auth.py deleted file mode 100644 index ec970e5..0000000 --- a/Backend/app/api/auth.py +++ /dev/null @@ -1,80 +0,0 @@ -from anyio import Path -from fastapi.security.oauth2 import OAuth2PasswordRequestForm -from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException, Response, UploadFile, status -from sqlalchemy.orm import Session - -from app.utils.oa2 import get_current_user -from ..schema import schemas, auth -from ..models import models -from ..database.configuration import get_db -from app.core import user -from ..utils import hash, token -# from app.services import storage - -router = APIRouter(tags=["Authentication"], prefix="/auth") - -@router.post("/login", response_model=auth.Token) -def login( - user_cred: OAuth2PasswordRequestForm = Depends(), - db: Session = Depends(get_db) -): - user: schemas.User = ( - db.query(models.User).filter(models.User.email == user_cred.username).first() - ) - - if not user: - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, detail=f"Invalid Credentials" - ) - if not hash.verify_password(user_cred.password, user.password): - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, detail=f"Incorrect password" - ) - - access_token = token.create_access_token(data={"sub": user.email}) - - return {"access_token": access_token, "token_type": "bearer"} - - -@router.post("/signup", response_model=schemas.ShowUser, status_code=status.HTTP_201_CREATED) -def create_user_account(new_user: schemas.User, db: Session = Depends(get_db)): - return user.create(new_user, db) - - -@router.post("/forgot-password") -def forgot_password( - user_email: schemas.UserForgotPassword, - background_tasks: BackgroundTasks, - db: Session = Depends(get_db) -): - user.forgot_password(user_email.email, background_tasks, db) - return Response(status_code=status.HTTP_200_OK) - - -@router.post("/update-password") -def update_password( - user_info: schemas.UserUpdatePassword, - db: Session = Depends(get_db), -): - user.hash_update_password(user_info, db) - return Response(status_code=status.HTTP_200_OK) - - -@router.post("/verify-account") -def verify_account( - background_tasks: BackgroundTasks, - user_email: schemas.UserVerifyAccount, - db: Session = Depends(get_db), -): - user.verify_user_account(user_email.email, background_tasks, db) - return Response(status_code=status.HTTP_200_OK) - - -@router.post("/confirm_verification") -def confirm_verification( - verify: schemas.VerificationCode, - db: Session = Depends(get_db), -): - user.confirm_verification(verify.code, verify.email, db) - return Response(status_code=status.HTTP_200_OK) - diff --git a/Backend/app/api/elective_course_api.py b/Backend/app/api/elective_course_api.py new file mode 100644 index 0000000..2b0ea68 --- /dev/null +++ b/Backend/app/api/elective_course_api.py @@ -0,0 +1,39 @@ +from typing import List +from fastapi import APIRouter, Depends, status +from app.db import db +from app.utils.oa2 import get_current_user +from ..schema import schemas + +router = APIRouter(tags=["Elective Courses"], prefix="/elective_course") + + +@router.get("/", response_model=List[schemas.ElectiveCourseOutput]) +def get_all_elective_courses(cur_user:schemas.UserOutput = Depends(get_current_user)): + courses = db.electivecourse.find_many() + return courses + +@router.get("/booked") +def get_booked_elective_courses(cur_user:schemas.UserOutput = Depends(get_current_user)): + courses = db.courserequest.find_many(where={"user_id":cur_user.id}) + return courses + +@router.post("/", response_model=schemas.ElectiveCourse, status_code=status.HTTP_201_CREATED) +def create_elective_course(course: schemas.ElectiveCourse, cur_user:schemas.UserOutput = Depends(get_current_user)): + courses: schemas.ElectiveCourse = db.electivecourse.create(data={ + "course_name": course.course_name, + "instructor_name": course.instructor_name, + "description": course.description, + "available_places": course.available_places if course.available_places else 0 + }) + return courses + + +@router.post("/request", status_code=status.HTTP_201_CREATED) +def request_elective_course(course_id: str, cur_user:schemas.UserOutput = Depends(get_current_user)): + user_id = cur_user.id + created_elective_request = db.courserequest.create(data={ + "user_id": user_id, + "course_id": course_id + }) + return {"data": created_elective_request, "status": status.HTTP_201_CREATED, + "detail": "request for elective course was created successfully"} \ No newline at end of file diff --git a/Backend/app/api/pass_request_api.py b/Backend/app/api/pass_request_api.py new file mode 100644 index 0000000..2b9042a --- /dev/null +++ b/Backend/app/api/pass_request_api.py @@ -0,0 +1,29 @@ +from fastapi import APIRouter, Depends, status +from app.db import db +from app.utils.oa2 import get_current_user +from ..schema import schemas + + +router = APIRouter(tags=["Obtain Pass"], prefix="/request_pass") + + +@router.get("/") +def get_all_pass_requests(cur_user:schemas.UserOutput = Depends(get_current_user)): + + pass_requests = db.passrequest.find_many(where={"user_id": cur_user.id},order={"requested_date": "desc"}) + return pass_requests + +@router.post("/", status_code=status.HTTP_201_CREATED) +def order_pass(pass_request: schemas.OrderPassRequest, cur_user:schemas.UserOutput = Depends(get_current_user)): + guest_info = "" + if pass_request.guests: + guest_info ="*_*".join(pass_request.guests) + + requested_pass = db.passrequest.create(data={ + "user_id": cur_user.id, + "description": pass_request.description, + "requested_date": pass_request.requested_date.isoformat(), + "guest_info": guest_info + }) + + return {"status": status.HTTP_201_CREATED, "detail": "Successfully created pass order"} \ No newline at end of file diff --git a/Backend/app/api/user_api.py b/Backend/app/api/user_api.py new file mode 100644 index 0000000..1b8d274 --- /dev/null +++ b/Backend/app/api/user_api.py @@ -0,0 +1,155 @@ + +from fastapi.security.oauth2 import OAuth2PasswordRequestForm +from fastapi.encoders import jsonable_encoder +from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException, Response, status + +from app.utils.oa2 import get_current_user +from ..schema import schemas + +# from ..database.configuration import get_db +from ..utils import hash, token, email_handler +from app.db import db + + +router = APIRouter(tags=["User Authentication"], prefix="/user") + + +@router.post("/login") +def login_alumni( + user_cred: OAuth2PasswordRequestForm = Depends() +): + user = db.user.find_first(where={"email": user_cred.username}) + print(user, user_cred) + if not user: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, detail=f"Invalid Credentials" + ) + if not hash.verify_password(user_cred.password, user.password): + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, detail=f"Incorrect password" + ) + + access_token = token.create_access_token(data={"sub": user.email}) + + return {"access_token": access_token, "token_type": "bearer"} + + +@router.post("/register",status_code=status.HTTP_201_CREATED) +def create_alumni_account(user_to_create: schemas.SignUpUser): + password = user_to_create.password + confirm_password = user_to_create.confirm_password + if password != confirm_password: + raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Password doesn't match Confirm password") + + new_user_email = user_to_create.email + found_user = db.user.find_first(where={"email": new_user_email}) + + # If user is found return with error + if found_user: + raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail='User with email already exists') + + encrypted_password = hash.hash_password(password) + db.user.create(data={ + "email": new_user_email, + "password": encrypted_password + }) + return { + "status": status.HTTP_201_CREATED, + "message": 'Successfully registered user' + } + + + +@router.post("/update", status_code=status.HTTP_201_CREATED, response_model=schemas.UserOutput) +def update_alumni_account(up_user: schemas.UpdateUser, + cur_user:schemas.InternalUser = Depends(get_current_user)): + updated_user = db.user.update(where={"id": cur_user.id}, + data={ + "name": up_user.name if up_user.name else cur_user.name, + "graduation_year": up_user.graduation_year if up_user.graduation_year else cur_user.graduation_year, + "field_of_study": up_user.field_of_study if up_user.field_of_study else cur_user.field_of_study, + "bio": up_user.bio if up_user.bio else cur_user.bio, + "city": up_user.city if up_user.city else cur_user.city, + "company": up_user.company if up_user.company else cur_user.company, + "position": up_user.position if up_user.position else cur_user.position, + "telegram_handle": up_user.telegram_handle if up_user.telegram_handle else cur_user.telegram_handle, + "telegram_id": up_user.telegram_id if up_user.telegram_id else cur_user.telegram_id, + "is_volunteer": up_user.is_volunteer if up_user.is_volunteer else cur_user.is_volunteer + }) + return updated_user + +@router.get("/", response_model=schemas.UserOutput, status_code=status.HTTP_200_OK) +def get_current_alumni(cur_user:schemas.UserOutput = Depends(get_current_user)): + return cur_user + + +@router.post("/forgot-password") +def forgot_password( + university_email: str, + background_tasks: BackgroundTasks, +): + # user.forgot_password(user_email.email, background_tasks, db) + user = db.user.find_first(where={"email": university_email}) + + if not user: + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND,detail="User not found") + + email_handler.send_email( + background_tasks, + 'Forgotten Password: Reset your password', + university_email, {'title': 'Welcome'}, + "forgot_password.html") + # background_tasks.add_task(reset_can_update_password, user, PASSWORD_RESET_INTERVAL, db) + + return Response(status_code=status.HTTP_200_OK) + + +@router.post("/update-password") +def update_password( + user_info, +): + # user.hash_update_password(user_info, db) + return Response(status_code=status.HTTP_200_OK) + + +@router.post("/verify-account") +def verify_account( + university_email: str, + background_tasks: BackgroundTasks +): + # user.verify_user_account(user_email.email, background_tasks, db) + user = db.user.find_first(where={"email": university_email}) + + if not user: + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND,detail="User not found") + if user.is_verified: + raise HTTPException(status_code=status.HTTP_202_ACCEPTED, detail="User already verified") + + verification_code = token.generate_user_verification_code() + db.user.update(where={"id": user.id}, data={"verification_code": verification_code}) + print(verification_code) + + email_handler.send_email(background_tasks, "Account Verification: Let's make sure it is you", university_email, {'verification_code': verification_code}, "account_verification.html") + # background_tasks.add_task(verification_expired, user, VERIFICATION_EXPIRATION_INTERVAL, db) + + return Response(status_code=status.HTTP_200_OK) + + +@router.post("/confirm_verification") +def confirm_verification( + verify:schemas.VerificationCode, +): + # user.confirm_verification(verify.code, verify.email, db) + user = db.user.find_first(where={"email": verify.email}) + + if not user: + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND,detail="User not found") + if user.is_verified: + raise HTTPException(status_code=status.HTTP_202_ACCEPTED, detail="User already verified") + if user.verification_code == "": + raise HTTPException(status_code=status.HTTP_406_NOT_ACCEPTABLE, detail="Verification code expired") + if user.verification_code != verify.code: + raise HTTPException(status_code=status.HTTP_406_NOT_ACCEPTABLE, detail="Incorrect code") + + db.user.update(where={"id":user.id}, data={"is_verified": True}) + return Response(status_code=status.HTTP_200_OK) diff --git a/Backend/app/config.py b/Backend/app/config.py new file mode 100644 index 0000000..f60f5f9 --- /dev/null +++ b/Backend/app/config.py @@ -0,0 +1,26 @@ +from pydantic import BaseSettings +from dotenv import load_dotenv +load_dotenv() + +class Settings(BaseSettings): + database_host: str + database_port: str + database_password: str + database_name: str + database_username: str + secret_key: str + algorithm: str + access_token_expire_minutes: str + + mail_username: str + mail_password: str + mail_from: str + mail_port: str + mail_server: str + mail_from_name: str + + class Config: + env_file = '.env' + env_file_encoding = 'utf-8' + +settings = Settings() \ No newline at end of file diff --git a/Backend/app/db.py b/Backend/app/db.py new file mode 100644 index 0000000..47b09ba --- /dev/null +++ b/Backend/app/db.py @@ -0,0 +1,3 @@ +from prisma import Prisma + +db = Prisma() \ No newline at end of file diff --git a/Backend/app/main.py b/Backend/app/main.py index 69b3580..37009e6 100644 --- a/Backend/app/main.py +++ b/Backend/app/main.py @@ -1,11 +1,13 @@ from fastapi import FastAPI from starlette.responses import HTMLResponse from fastapi.middleware.cors import CORSMiddleware +from app.db import db +from app.telegram.init import setup_telegram_bot +from app.version import router as final_router # import sys # print(sys.executable) # print(sys.path) -from app.version import router as final_router app = FastAPI( @@ -26,7 +28,22 @@ app.include_router(final_router, prefix="/api/v1") -@app.get("/", response_class=HTMLResponse) +@app.on_event("startup") +def startup(): + print(f'db connected...') + db.connect() + + # Running telegram bot + setup_telegram_bot() + + +@app.on_event("shutdown") +def shutdown(): + print(f'db disconnected...') + db.disconnect() + + +@app.get("/", response_class=HTMLResponse, include_in_schema=False) def index(): return """ @@ -38,9 +55,9 @@ def index():
-

AlumniPortalAPI

+

AlumniPortal API Docs

diff --git a/Backend/app/prisma/schema.prisma b/Backend/app/prisma/schema.prisma new file mode 100644 index 0000000..5a43098 --- /dev/null +++ b/Backend/app/prisma/schema.prisma @@ -0,0 +1,92 @@ +generator db { + provider = "prisma-client-py" + recursive_type_depth = "2" + interface = "sync" +} + +datasource db { + provider = "postgresql" + url = "postgres://alumni_portal_db_user:o7NcbLeRirYftmcMTLKAtGBCfjh46F6t@dpg-cigldflgkuvojj9uh32g-a.oregon-postgres.render.com/alumni_portal_db" + // url = "postgres://postgres:postgres@127.0.0.1:5432/inno_schedule" +} + +model User { + id String @id @default(cuid()) + name String? + email String + + name_russian String? + graduation_year Int? + field_of_study String? + bio String? + city String? + company String? + position String? + telegram_handle String? + telegram_id BigInt? @unique + + is_volunteer Boolean @default(false) + is_verified Boolean @default(false) + verification_code Int? + + course_request CourseRequest[] + pass_request PassRequest[] + + elective_course_id String? + elective_course ElectiveCourse? @relation(fields: [elective_course_id], references: [id]) + + password String + created_at DateTime @default(now()) + updated_at DateTime @updatedAt +} + +model ElectiveCourse { + id String @id @default(cuid()) + description String + course_name String? + instructor_name String? + + available_places Int? + + users User[] + request CourseRequest[] +} + +model PassRequest { + id String @id @default(cuid()) + description String? + guest_info String? + feedback String? + type RequestType @default(PASS) + requested_date String + status RequestStatus @default(PENDING) + user_id String + user User @relation(fields: [user_id], references: [id]) + created_at DateTime @default(now()) +} + +model CourseRequest { + id String @id @default(cuid()) + feedback String? + + status RequestStatus @default(PENDING) + user_id String + user User? @relation(fields: [user_id], references: [id]) + + course_id String? + elective_course ElectiveCourse? @relation(fields: [course_id], references: [id]) + + created_at DateTime @default(now()) + updated_at DateTime @updatedAt +} + +enum RequestStatus { + APPROVED + REJECTED + PENDING +} + +enum RequestType { + PASS + VOLUNTEER +} diff --git a/Backend/app/schema/schemas.py b/Backend/app/schema/schemas.py new file mode 100644 index 0000000..dbc273d --- /dev/null +++ b/Backend/app/schema/schemas.py @@ -0,0 +1,192 @@ +from enum import Enum +import datetime +from typing import List, Optional +from pydantic import BaseModel, EmailStr + +####### USER SCHEMAS +####################################### + +class InternalUser(BaseModel): + id: str + email: EmailStr + name: Optional[str] + graduation_year: Optional[int] + field_of_study: Optional[str] + bio: Optional[str] + city: Optional[str] + company: Optional[str] + position: Optional[str] + telegram_handle: Optional[str] + telegram_id: Optional[int] + is_volunteer: Optional[bool] + +class LogInUser(BaseModel): + email: EmailStr + password: str + + + +class SignUpUser(BaseModel): + email: EmailStr + password: str + confirm_password: str + +class UpdateUser(BaseModel): + name: Optional[str] + graduation_year: Optional[int] + field_of_study: Optional[str] + bio: Optional[str] + city: Optional[str] + company: Optional[str] + position: Optional[str] + telegram_handle: Optional[str] + telegram_id: Optional[int] + is_volunteer: Optional[bool] + + class Config(): + orm_mode = True + +class UserOutput(BaseModel): + name: Optional[str] + email: EmailStr + graduation_year: Optional[int] + telegram_id: Optional[int] + telegram_handle: Optional[str] + position: Optional[str] + company: Optional[str] + city: Optional[str] + bio: Optional[str] + field_of_study: Optional[str] + is_volunteer: Optional[bool] + + class Config(): + orm_mode = True + + +class ConfirmationCode(BaseModel): + code: int + + + +####### ORDER PASS SCHEMAS +####################################### + +class OrderPassRequest(BaseModel): + requested_date: Optional[datetime.date] + guests: Optional[List[str]] = None + description: Optional[str] = None + + + + +####### ELECTIVE COURSE SCHEMAS +####################################### + +class ElectiveCourse(BaseModel): + course_name: str + instructor_name: Optional[str] = None + description: Optional[str] = None + available_places: Optional[int] = None + + +class ElectiveCourseOutput(BaseModel): + id: str + course_name: str + instructor_name: Optional[str] = None + description: Optional[str] = None + available_places: Optional[int] = None + + + + + + +class ShowUser(BaseModel): + full_name: str + email: str + + class Config(): + orm_mode = True + + +class User(BaseModel): + email: EmailStr + password: str + + +class UserForgotPassword(BaseModel): + email: EmailStr + + +class UserVerifyAccount(BaseModel): + email: EmailStr + + +class UserUpdatePassword(BaseModel): + email: EmailStr + password: str + + +class VerificationCode(BaseModel): + code: str + email: EmailStr + + +class UserOut(BaseModel): + full_name: str + email: EmailStr + phone_number: Optional[str] + address: Optional[str] + avatar: Optional[str] + birth_date: Optional[datetime.date] + country: Optional[str] + + class Config(): + orm_mode = True + + +class UserEdit(BaseModel): + address: Optional[str] + avatar: Optional[str] + + +class SlotTypeEnum(str, Enum): + LAB = "LAB" + TUT = "TUT" + LEC = "LEC" + + +class Slot(BaseModel): + instructor_name: Optional[str] + room_number: Optional[str] + start_time: datetime.datetime + end_time: datetime.datetime + course_name: Optional[str] + type: Optional[SlotTypeEnum] + course_id: str + group_id: str + + class Config(): + orm_mode = True + + +class SlotUpdate(BaseModel): + instructor_name: Optional[str] + room_number: Optional[str] + start_time: Optional[datetime.datetime] + end_time: Optional[datetime.datetime] + course_name: Optional[str] + type: Optional[SlotTypeEnum] + course_id: Optional[str] + group_id: Optional[str] + + class Config(): + orm_mode = True + + +class SlotRange(BaseModel): + start_date: datetime.date + end_date: datetime.date + + class Config(): + orm_mode = True diff --git a/Backend/app/telegram/admin/controller.py b/Backend/app/telegram/admin/controller.py new file mode 100644 index 0000000..b9439c3 --- /dev/null +++ b/Backend/app/telegram/admin/controller.py @@ -0,0 +1,41 @@ +from app.db import db +from app.telegram import data + + +def get_all_users(): + return db.user.find_many() + + +def get_user_by_alias(user_handle): + return db.user.find_first(where={"handle": user_handle}) + + +def get_elective_courses(): + return db.course.find_many( + where={"is_elective": True} + ) + + +def get_groups(): + return db.group.find_many() + + +def get_group_users(group_name): + group = db.group.find_first( + where={"specific_group": group_name}, include={"users": True}) + if not group: + return [] + return group.users + + +def get_elective_course_users(course_short_name): + course = db.course.find_first( + where={"short_name": course_short_name}, + include={"optional_course_users": True, "elective_users": True}) + if not course: + return [] + if course.valid_group == 'ALL': + users = course.optional_course_users + else: + users = course.elective_users + return users diff --git a/Backend/app/telegram/admin/data.py b/Backend/app/telegram/admin/data.py new file mode 100644 index 0000000..64bc051 --- /dev/null +++ b/Backend/app/telegram/admin/data.py @@ -0,0 +1,25 @@ +MODULE_NAME = "admin" + +# "625620708:AAFII7HO_Anlcn0pLMUN9Y_HNkTDJ0MLctc" - worksilently_bot +# TOKEN = "6057962313:AAEEDkC3cDA0j3JQBsqr6FlMorSPzXQ7uvs" + +MESSAGE_AMOUNT = "People registered: " +MESSAGE_UNAUTHORIZED = "Unauthorized access attempt. Administrator was notified" +MESSAGE_SENT_EVERYBODY = "Message has been sent to everybody" +MESSAGE_SENT_PERSONAL = "Message has been sent" +MESSAGE_ABORTED = "Aborted" +MESSAGE_USER_NOT_FOUND = "User not found" +MESSAGE_EXCEPTION = "Exception occurred:\n" +MESSAGE_SCHEDULE_UPDATED = "Schedule is updated" +MESSAGE_ERROR = "Sorry, I did not understand you" + +REQUEST_SPAM_COURSE_MESSAGE = "With great power comes great responsibility!\nWhat do you want to send to a whole course?" +REQUEST_SPAM_GROUP_MESSAGE = "With great power comes great responsibility!\nWhat do you want to send to a whole group?" +REQUEST_SPAM_MESSAGE = "With great power comes great responsibility!\nWhat do you want to send to everyone?" +REQUEST_PERSONAL_ALIAS = "Write telegram alias for personal message" +REQUEST_PERSONAL_MESSAGE = "Write your personal message to " +REQUEST_COURSE = "What course to spam?" +REQUEST_GROUP = "What group to spam?" + +ADMIN_LIST = [498255810] +SUPERADMIN_LIST = [498255810] diff --git a/Backend/app/telegram/admin/handlers.py b/Backend/app/telegram/admin/handlers.py new file mode 100644 index 0000000..3fd1ceb --- /dev/null +++ b/Backend/app/telegram/admin/handlers.py @@ -0,0 +1,144 @@ +import telebot +from app.telegram.core_handlers import bot, log +from app.telegram.admin import controller +from app.telegram.admin import data + + +def attach_admin_module(): + admin_commands = ['die', 'log', 'spam', 'pm', + 'helpa', 'spam_course', 'spam_group'] + + @bot.message_handler(commands=admin_commands) + def admin(message): + """ + Register module's commands + """ + log(data.MODULE_NAME, message) + # only admins from list are allowed to call admin commands + if message.from_user.id not in data.ADMIN_LIST: + bot.send_message(message.chat.id, data.MESSAGE_UNAUTHORIZED) + return + + if message.text == "/die": + if message.from_user.id not in data.SUPERADMIN_LIST: + return + raise Exception + elif message.text == '/log': + bot.send_document(message.chat.id, open('log', 'rb')) + elif message.text == '/spam': + if message.from_user.id not in data.SUPERADMIN_LIST: + return + msg = bot.send_message( + message.chat.id, data.REQUEST_SPAM_MESSAGE) + users = controller.get_all_users() + user_ids = list(map(lambda x: x.id, users)) + bot.register_next_step_handler(msg, process_spam_step, user_ids) + elif message.text == '/spam_course': + if message.from_user.id not in data.SUPERADMIN_LIST: + return + options = telebot.types.ReplyKeyboardMarkup(True, False) + # add buttons to choose course + elective_courses = controller.get_elective_courses() + short_names = list( + map(lambda course: course.short_name, elective_courses)) + options.add(*short_names) + msg = bot.send_message( + message.chat.id, data.REQUEST_COURSE, reply_markup=options) + bot.register_next_step_handler( + msg, process_course_step, short_names) + elif message.text == '/spam_group': + if message.from_user.id not in data.SUPERADMIN_LIST: + return + options = telebot.types.ReplyKeyboardMarkup(True, False) + # add buttons to choose course + groups = controller.get_groups() + short_names = list( + map(lambda grp: grp.specific_group, groups)) + options.add(*short_names) + msg = bot.send_message( + message.chat.id, data.REQUEST_GROUP, reply_markup=options) + bot.register_next_step_handler( + msg, process_group_step, short_names) + elif message.text == '/pm': + # private message to specific user + msg = bot.send_message( + message.chat.id, data.REQUEST_PERSONAL_ALIAS) + bot.register_next_step_handler(msg, process_pm_alias_step) + elif message.text == '/helpa': + # send admin commands help + bot.send_message( + message.chat.id, f"VALID ADMIN COMMANDS:\n{' '.join(admin_commands)}") + + def process_course_step(message, short_names): + log(data.MODULE_NAME, message) + if not message.text: + bot.send_message(message.chat.id, data.MESSAGE_ABORTED) + return + if message.text == "C": + bot.send_message(message.chat.id, data.MESSAGE_ABORTED) + return + if message.text not in short_names: + bot.send_message(message.chat.id, data.MESSAGE_ERROR) + return + elective_course = message.text + users = controller.get_elective_course_users(elective_course) + user_ids = list(map(lambda x: x.id, users)) + print(user_ids) + msg = bot.send_message(message.chat.id, data.REQUEST_SPAM_COURSE_MESSAGE, + reply_markup=telebot.types.ReplyKeyboardRemove()) + bot.register_next_step_handler(msg, process_spam_step, user_ids) + + def process_group_step(message, group_names): + log(data.MODULE_NAME, message) + if not message.text: + bot.send_message(message.chat.id, data.MESSAGE_ABORTED) + return + if message.text == "C": + bot.send_message(message.chat.id, data.MESSAGE_ABORTED) + return + if message.text not in group_names: + bot.send_message(message.chat.id, data.MESSAGE_ERROR) + return + group_name = message.text + users = controller.get_group_users(group_name) + user_ids = list(map(lambda x: x.id, users)) + + msg = bot.send_message(message.chat.id, data.REQUEST_SPAM_GROUP_MESSAGE, + reply_markup=telebot.types.ReplyKeyboardRemove()) + bot.register_next_step_handler(msg, process_spam_step, user_ids) + + def process_spam_step(message, user_ids=[]): + log(data.MODULE_NAME, message) + # abort operation if needed + if message.text == "C": + bot.send_message(message.chat.id, data.MESSAGE_ABORTED) + return + # iterate over all users and SPAM + for id in user_ids: + try: + bot.send_message(id, message.text) + except: + print(f"Error happened while sending mass message to {id}") + continue + bot.send_message(message.chat.id, data.MESSAGE_SENT_EVERYBODY) + + def process_pm_alias_step(message): + """ + Get alias of user to send private message + """ + log(data.MODULE_NAME, message) + # abort operation if needed + if message.text == "C": + bot.send_message(message.chat.id, data.MESSAGE_ABORTED) + return + alias = message.text.strip() + # remove '@' at beginning + if alias[0] == '@': + alias = alias[1:] + user = controller.get_user_by_alias(alias) + if user is None: + bot.send_message(message.chat.id, data.MESSAGE_USER_NOT_FOUND) + return + msg = bot.send_message( + message.chat.id, f"{data.REQUEST_PERSONAL_MESSAGE}{alias}") + bot.register_next_step_handler(msg, process_spam_step, [user.id]) diff --git a/Backend/app/telegram/controller.py b/Backend/app/telegram/controller.py new file mode 100644 index 0000000..4419bd4 --- /dev/null +++ b/Backend/app/telegram/controller.py @@ -0,0 +1,263 @@ +from datetime import datetime +from app.telegram import data +from app.db import db + +# USERS RELATED + + +def get_user(user_id): + user = db.user.find_unique(where={'telegram_id': user_id}) + return user + +def get_full_user(user_id): + user = db.user.find_unique( + where={'telegram_id': user_id}, + include={'pass_request': True, 'course_request': True} + ) + return user + +def register_user(user_id, email="", fullname="", handle=""): + return db.user.create(data={ + "telegram_id": user_id, + "telegram_handle": handle, + "email": email, + "name": fullname, + }) + +def update_user(user_id, email="", fullname="", handle=""): + return db.user.update(data={ + "telegram_handle": handle, + "email": email, + "name": fullname, + }, where={ + "telegram_id": user_id + }) + +def update_user_alias(user_id, handle): + return db.user.update(where={'telegram_id': user_id}, data={"telegram_handle": handle}) + + + + + +def get_user_with_settings(user_id): + user = db.user.find_unique( + where={'telegram_id': user_id}) + return user + + +def get_user_with_course(user_id): + user = db.user.find_unique( + where={'telegram_id': user_id}, include={"course_request": True}) + return user + + +# GENERAL REQUESTS + +# not done yet +def print_request(request): + date = datetime.strptime( + f"{request.created_at}", "%Y-%m-%d %H:%M:%S.%f%z") + result = "" + if request.type == 'ELECTIVE': + result += f"ELECTIVE request is {request.status} for {request.course.description} - {date.strftime('%d/%m/%Y')}\n" + else: + result += f"{request.type} request is {request.status} - {date.strftime('%d/%m/%Y')}\n" + return result + +# not done yet +def print_request_result(request): + date = datetime.strptime( + f"{request.created_at}", "%Y-%m-%d %H:%M:%S.%f%z") + result = "" + if request.type == 'ELECTIVE': + result += f"ELECTIVE request has been {request.status} for {request.course.description} - {date.strftime('%d/%m/%Y')}\n" + else: + result += f"PASS request has been {request.status} - {date.strftime('%d/%m/%Y')}\n" + return result + + +def get_pass_request(user_id): + requests = db.passrequest.find_many( + where={'user_id': user_id}, + order={'created_at': 'desc'} + ) + return requests + +def get_course_request(user_id): + requests = db.courserequest.find_many( + where={'user_id': user_id}, + include={'elective_course': True}, + order={'created_at': 'desc'} + ) + return requests + +def get_pass_request_by_id(request_id): + return db.passrequest.find_unique(where={"id":request_id}) + +def get_course_request_by_id(request_id): + return db.courserequest.find_unique(where={"id":request_id}) + +def clear_pass_request_history(user_id): + requests = db.passrequest.delete_many( + where={'user_id': user_id, + 'status': { + "in": ["APPROVED", "REJECTED"] + } + }) + return requests + +def clear_course_request_history(user_id): + requests = db.courserequest.delete_many( + where={'user_id': user_id, + 'status': { + "in": ["APPROVED", "REJECTED"] + } + }) + return requests +# '2023-03-24 08:11:10.059000+00:00' does not match format '%d/%m' + +# ELECTIVE RELATED + +# not done yet +def update_user_courses(user_id, course_id): + return db.user.update( + data={ + "courses": { + "connect": { + "telegram_id": course_id + } + } + }, + where={"telegram_id": user_id} + ) + +def get_pending_elective_request(user_id): + requests = db.courserequest.find_many( + where={'user_id': user_id, "status": "PENDING"}, + include={'elective_course': True} + ) + return requests + +def get_pending_pass_requests(user_id): + return db.passrequest.find_many( + where={'user_id': user_id, "status": "PENDING"}, + include={'user': True} + ) + +def clear_pending_elective_request(user_id): + deleted = db.courserequest.delete_many( + where={'user_id': user_id, "status": "PENDING"}, + ) + return deleted + + +def get_elective_courses(): + elective_courses = db.electivecourse.find_many() + return elective_courses + +def get_elective_by_name(elective_name): + return db.electivecourse.find_first(where={"name": elective_name}) + +def request_elective(elective, user_id): + course = db.electivecourse.find_first(where={"name": elective}) + if not course: + return [] + + return db.courserequest.create(data={ + "user_id": user_id, + "course_id": course.id + }) + + +def clear_elective_courses(user_id, ids_to_disconnect): + return db.user.update( + data={ + "courses": { + "disconnect": ids_to_disconnect + } + }, where={"telegram_id": user_id}) + + +def get_electives(user_id): + user = db.user.find_unique( + where={"telegram_id": user_id}, + include={"course_request": True} + ) + return user.elective_courses + + +# PASS RELATED + +def request_pass(requested_date, description, user_id): + user = db.user.find_unique(where={"telegram_id": user_id}) + return db.passrequest.create(data={ + "user_id": user.id, + "description": description, + "requested_date": requested_date + }) + + +def approve_pass_request(request_id, feedback): + try: + request = db.passrequest.update( + data={"status": "APPROVED", "feedback": feedback}, + where={"id": request_id}) + except: + print( + f"Error: Probably request with id - {request_id} does not exist anymore") + return request + +def approve_course_request(request_id, feedback): + try: + request = db.courserequest.update( + data={"status": "APPROVED", "feedback": feedback}, + where={"id": request_id}, include={"elective_course": True}) + except: + print( + f"Error: Probably request with id - {request_id} does not exist anymore") + return request + +def reject_pass_request(request_id, feedback): + try: + request = db.passrequest.update( + data={"status": "REJECTED", "feedback": feedback}, + where={"id": request_id}) + except: + print( + f"Error: Probably request with id - {request_id} does not exist anymore") + return request + +def reject_course_request(request_id, feedback): + try: + request = db.courserequest.update( + data={"status": "REJECTED", "feedback": feedback}, + where={"id": request_id}, + include={'elective_course': True}) + except: + print( + f"Error: Probably request with id - {request_id} does not exist anymore") + return request + +def get_pending_pass_request(user_id): + user = db.user.find_unique(where={"telegram_id": user_id}) + requests = db.passrequest.find_many( + where={'user_id': user.id, "status": "PENDING"} + ) + return requests + + +def delete_pending_pass_request(user_id): + user = db.user.find_unique(where={"telegram_id": user_id}) + deleted = db.passrequest.delete_many( + where={'user_id': user.id, "status": "PENDING"}, + ) + return deleted + + +# \copy public."Slot" (telegram_id, instructor_name, room_number, start_time, end_time, course_id, type, group_id, specific_group, course_name) FROM '/Users/danielatonge/Downloads/week3_schedule/slot.csv' DELIMITER ',' CSV HEADER QUOTE '"' ESCAPE ''''; + + +############### +# Helper methods +############### diff --git a/Backend/app/telegram/core_handlers.py b/Backend/app/telegram/core_handlers.py new file mode 100644 index 0000000..d5dc7e3 --- /dev/null +++ b/Backend/app/telegram/core_handlers.py @@ -0,0 +1,179 @@ +import time +import telebot +import logging +from threading import Thread +from logging.handlers import RotatingFileHandler +from app.telegram import data, controller +from app.telegram.admin.data import SUPERADMIN_LIST + +MODULE_NAME = "core" +bot = telebot.TeleBot(token=data.TOKEN) + + +main_markup = telebot.types.ReplyKeyboardMarkup(True) +main_markup.add(data.TEXT_BUTTON_PASS, data.TEXT_BUTTON_ELECTIVE, data.TEXT_BUTTON_PROFILE, + data.TEXT_BUTTON_DONATE) + +commands = [ + telebot.types.BotCommand("start", "starts InnoAlumni bot"), + # telebot.types.BotCommand("register", "simple profile setup"), + # telebot.types.BotCommand("register_and_auth", "Register and authenticate"), + telebot.types.BotCommand( + "profile", "View my profile information and status of requests"), + telebot.types.BotCommand("request_elective", "Request an elective course"), + telebot.types.BotCommand( + "clear_electives", "Cancel all pending request for electives"), + telebot.types.BotCommand( + "request_pass", "Request guest entrance passes on arrival to IU"), + telebot.types.BotCommand( + "cancel_pass", "Cancel pass request"), + telebot.types.BotCommand( + "donate", "Get a link you can use to securely donate to Alumni Club"), + telebot.types.BotCommand( + "volunteer", "Get urgent access to the university campus"), + # telebot.types.BotCommand( + # "cancel", "Exit from any user flow process while using the bot"), + # telebot.types.BotCommand("upload_certificate", + # "Upload a copy of your diploma "), + # telebot.types.BotCommand( + # "config_remind", "Remind me of any status updates (true by default)"), + telebot.types.BotCommand( + "feedback", "Suggest improvements and share bugs"), + telebot.types.BotCommand("help", "Overview of bot commands"), +] +# log configuration +logger = logging.getLogger(data.LOG_NAME) +logger.setLevel(logging.INFO) +handler = RotatingFileHandler(data.LOG_FILE_NAME, maxBytes=data.LOG_MAX_SIZE_BYTES, + backupCount=data.LOG_BACKUP_COUNT) +handler.setFormatter(logging.Formatter( + data.LOG_MESSAGE_FORMAT, data.LOG_DATE_FORMAT)) +logger.addHandler(handler) + + +def log(module, message): + if message.from_user.username: + user = message.from_user.username + else: + user = str(message.from_user.id) + logger.info(f"{module.rjust(15)} :: {user.rjust(20)} ::" + f"{message.text if message.text else '--not_text--'}") + + +def attach_core_module(): + fullname = None + + @bot.message_handler(commands=['start']) + def start_command(message): + log(MODULE_NAME, message) + print(f"USER {message.from_user.id} clicked start") + bot.send_message(message.chat.id, data.MESSAGE_HI, reply_markup=main_markup) + user = controller.get_user(message.from_user.id) + if user is None: + bot.send_message(message.chat.id, data.REGISTER_START, reply_markup=main_markup) + msg = bot.send_message(message.chat.id, data.REGISTER_PROMPT_FULLNAME, + reply_markup=main_markup) + bot.register_next_step_handler(msg, process_register_fullname_step) + + def process_register_fullname_step(message): + log(MODULE_NAME, message) + if not message.text: + bot.send_message(message.chat.id, data.MESSAGE_ERROR, + reply_markup=main_markup) + return + if message.text == "/cancel": + bot.send_message(message.chat.id, data.MESSAGE_CANCEL, + reply_markup=main_markup) + return + global fullname + fullname = message.text + msg = bot.send_message(message.chat.id, data.REGISTER_PROMPT_EMAIL, + reply_markup=main_markup) + bot.register_next_step_handler(msg, process_register_email_step) + + def process_register_email_step(message): + log(MODULE_NAME, message) + if not message.text: + bot.send_message(message.chat.id, data.MESSAGE_ERROR, + reply_markup=main_markup) + return + if message.text == "/cancel": + bot.send_message(message.chat.id, data.MESSAGE_CANCEL, + reply_markup=main_markup) + return + email = message.text + global fullname + controller.register_user(message.from_user.id, email, fullname, message.from_user.username) + bot.send_message(message.chat.id, data.REGISTER_SUCCESS, + reply_markup=main_markup) + + + + + + @bot.message_handler(commands=['help']) + def help_command(message): + log(MODULE_NAME, message) + print(f"USER {message.from_user.id} clicked help") + bot.send_message(message.chat.id, data.MESSAGE_HELP, + reply_markup=main_markup) + + @bot.message_handler(commands=['feedback']) + def send_feedback(message): + log(MODULE_NAME, message) + print(f"USER {message.from_user.id} wants to send feedback") + user = controller.get_user(message.from_user.id) + if not user: + bot.send_message( + message.chat.id, data.MESSAGE_REGISTER_ACCOUNT, reply_markup=main_markup) + return + msg = bot.send_message(message.chat.id, data.FEEDBACK_PROMPT, + reply_markup=main_markup) + bot.register_next_step_handler(msg, process_feedback_step) + + def process_feedback_step(message): + log(MODULE_NAME, message) + if not message.text: + bot.send_message(message.chat.id, data.MESSAGE_ERROR, + reply_markup=main_markup) + return + + user = controller.get_user(message.from_user.id) + if not user: + return + alias = user.handle if user.handle else user.id + feedback = message.text + for admin in SUPERADMIN_LIST: + bot.send_message( + admin, f"{data.MESSAGE_FEEDBACK} {str(alias)}:\n{feedback}") + bot.send_message(message.chat.id, data.FEEDBACK_SUCCESS, + reply_markup=main_markup) + + +def compose_attached_modules(set_proxy=False): + + @bot.message_handler() + def garbage_message_handler(message): + """ + Fallback handler for unknown messages + To be called after all other modules have mounted their handlers + """ + log(MODULE_NAME, message) + # You could implement chatgpt or just Q&A over here + bot.send_message(message.chat.id, data.MESSAGE_ERROR, + reply_markup=main_markup) + user = controller.get_user(message.from_user.id) + if not user: + return + alias = user.handle if user.handle else user.id + for admin in SUPERADMIN_LIST: + bot.send_message( + admin, f"{data.MESSAGE_UNKNOWN} {str(alias)}:\n{message.text}") + + def polling_telegram_bot_commands(): + print("Bot begins polling") + bot.infinity_polling(long_polling_timeout=5, timeout=10) + + # bot.delete_my_commands() + # bot.set_my_commands(commands=commands) + Thread(target=polling_telegram_bot_commands, daemon=True).start() diff --git a/Backend/app/telegram/course_handlers.py b/Backend/app/telegram/course_handlers.py new file mode 100644 index 0000000..d32b015 --- /dev/null +++ b/Backend/app/telegram/course_handlers.py @@ -0,0 +1,149 @@ +from functools import reduce +from app.telegram.core_handlers import bot, log, main_markup +from app.telegram import data, controller +from telebot.types import ReplyKeyboardMarkup, InlineKeyboardMarkup, InlineKeyboardButton + + +MODULE_NAME="ELECTIVES" + +def attach_elective_module(): + + @bot.message_handler(regexp=f"^{data.TEXT_BUTTON_ELECTIVE}$") + def list_electives(message): + log(MODULE_NAME, message) + print(f"LIST ELECTIVE pressed by {message.from_user.id}") + user = controller.get_user(message.from_user.id) + if not user: + bot.send_message( + message.chat.id, data.MESSAGE_REGISTER_ACCOUNT, reply_markup=main_markup) + return + + elective_courses = controller.get_elective_courses() + + course_details = reduce( + lambda acc, x: f"{x.name} - {x.description}\n\n{acc}", + elective_courses, "") + course_details += f"\nClick on:\n/request_elective - Request participation in an elective course\n" \ + + f"/clear_electives - Cancel all pending request for electives" + if not elective_courses: + bot.send_message( + message.chat.id, "There are no available elective courses", ) + return + bot.send_message( + message.chat.id, course_details) + + def handle_request_elective(message): + if message.data == 'ACCEPT_REQUEST': + request_id = message.message.text.split('[')[1].split(']')[0] + print(request_id) + request = controller.approve_request(request_id) + request_result = controller.print_request_result(request) + bot.send_message(request.user_id, request_result, reply_markup=main_markup) + controller.update_user_courses(request.user_id, request.course_id) + + request_text = f"{message.message.text}\n\nStaff with telegram alias @{message.from_user.username} APPROVED ELECTIVE REQUEST." + for id in data.ALUMNI_OFFICE_LIST: + try: + bot.edit_message_text( + message_id=message.message.id, chat_id=id, text=request_text, reply_markup=InlineKeyboardMarkup()) + except: + print( + f"Error happened while sending volunteer message to {id}") + continue + elif message.data == 'REFUSE_REQUEST': + request_id = message.message.text.split('[')[1].split(']')[0] + print(request_id) + request = controller.reject_request(request_id) + request_result = controller.print_request_result(request) + bot.send_message(request.user_id, request_result, reply_markup=main_markup) + + request_text = f"{message.message.text}\n\nStaff with telegram alias @{message.from_user.username} REJECTED ELECTIVE REQUEST." + for id in data.ALUMNI_OFFICE_LIST: + try: + bot.edit_message_text( + message_id=message.message.id, chat_id=id, text=request_text, reply_markup=InlineKeyboardMarkup()) + except: + print( + f"Error happened while sending volunteer message to {id}") + continue + + @bot.message_handler(commands=['request_elective']) + @bot.callback_query_handler(handle_request_elective) + def elective_configuration(message): + log(MODULE_NAME, message) + print(f"REQUEST ELECTIVE pressed by {message.from_user.id}") + user = controller.get_user(message.from_user.id) + if not user: + bot.send_message( + message.chat.id, data.MESSAGE_REGISTER_ACCOUNT, reply_markup=main_markup) + return + + options = ReplyKeyboardMarkup(True, False) + + elective_courses = controller.get_elective_courses() + if not elective_courses: + bot.send_message( + message.chat.id, "There are no available elective courses", ) + return + course_abbrevations = list(map(lambda x: x.name, elective_courses)) + + options.add(*course_abbrevations) + msg = bot.send_message( + message.chat.id, data.REQUEST_ELECTIVE, reply_markup=options) + bot.register_next_step_handler( + msg, process_elective_step, course_abbrevations) + + def process_elective_step(message, elective_courses): + log(MODULE_NAME, message) + if not message.text: + bot.send_message(message.chat.id, data.MESSAGE_ERROR, + reply_markup=main_markup) + return + + elective = message.text + if elective not in elective_courses: + bot.send_message(message.chat.id, data.MESSAGE_ERROR, + reply_markup=main_markup) + return + elective_object = controller.get_elective_by_name(elective) + user = controller.get_user(message.from_user.id) + description = f"ELECTIVE REQUEST\n\nhandle: \n@{user.handle}\n\nEmail: \n{user.email}\n\nFull names: \n{user.fullnames}\n\n" + \ + f"Elective name: \n{elective_object.name}\n\nElective description: \n{elective_object.description}" + request = controller.request_elective(elective, message.from_user.id, description) + description = f"[{request.id}]\n\n{description}" + keyboard = [ + [ + InlineKeyboardButton( + data.APPROVE_REQUEST, callback_data="ACCEPT_REQUEST") + ], + [ + InlineKeyboardButton( + data.REJECT_REQUEST, callback_data="REFUSE_REQUEST") + ], + ] + reply_markup = InlineKeyboardMarkup(keyboard) + + for id in data.ALUMNI_OFFICE_LIST: + try: + bot.send_message(id, description, reply_markup=reply_markup) + except: + print( + f"Error happened while sending pass request message to {id}") + continue + bot.send_message( + message.chat.id, data.MESSAGE_ELECTIVE_REQUEST_SUCCESSFUL, reply_markup=main_markup) + + @bot.message_handler(commands=['clear_electives']) + def remove_elective(message): + log(MODULE_NAME, message) + print(f"REMOVE ELECTIVE pressed by {message.from_user.id}") + requests = controller.get_pending_elective_request( + message.from_user.id) + + if not requests: + bot.send_message( + message.chat.id, "No pending request for elective courses", reply_markup=main_markup) + return + controller.clear_pending_elective_request(message.from_user.id) + bot.send_message( + message.chat.id, data.CLEARED_ELECTIVE, reply_markup=main_markup) diff --git a/Backend/app/telegram/data.py b/Backend/app/telegram/data.py new file mode 100644 index 0000000..3d27102 --- /dev/null +++ b/Backend/app/telegram/data.py @@ -0,0 +1,161 @@ +TOKEN = "625620708:AAFII7HO_Anlcn0pLMUN9Y_HNkTDJ0MLctc" # - alumni_bot + + +TEXT_BUTTON_PASS = "PASS🃏" +TEXT_BUTTON_ELECTIVE = "ELECTIVES📓" +TEXT_BUTTON_DONATE = "DONATE💰" +TEXT_BUTTON_PROFILE = "PROFILE👤" + + +MESSAGE_HI = "Hi there, I am InnoAlumniBot!✋" +MESSAGE_HELP = "Simple assistant for Innopolis Alumni Community.\n\n" \ + "Some useful commands:\n" \ + "/register - Simple profile setup\n" \ + "/profile - View my profile information and status of requests\n" \ + "/request_elective - Request an elective course\n" \ + "/clear_electives - Cancel all pending request for electives\n" \ + "/request_pass - Request guest entrance passes on arrival to IU\n" \ + "/cancel_pass - Cancel pass request\n" \ + "/donate - Get a link where you can securely donate to Alumni Club\n" \ + "/volunteer - Get urgent access to the university campus\n" \ + "/feedback - Suggest improvements and share bugs\n\nContact @Hardriive for your suggestions." +# "/register_and_auth - Register and authenticate\n" \ +# "/upload_certificate - Upload a copy of your diploma\n" \ +# "/config_remind - Remind me of any status updates (true by default)\n" \ + +MESSAGE_ERROR = "Sorry, I did not understand you. Aborting command ..." + +MESSAGE_CANCEL = "Process successfully cancelled" +MESSAGE_UNKNOWN = "Unknown message from" +MESSAGE_FEEDBACK = "Feedback message from" +FEEDBACK_PROMPT = "Leave your feedback" +FEEDBACK_SUCCESS = "Your feedback was successfully received.\nThe InnoAlumni bot team will review your feedback and contact you if necessary within the next 24hrs" +ERROR_PROMPT = "Sorry, an error occurred. Try again later." + +MESSAGE_USER_NOT_configD = "Sorry. I do not know your groups yet. 😥\n" \ + "Please use /config_schedule command to set it up" +MESSAGE_FREE_DAY = "No lessons on this day! Lucky you are!" + + +MESSAGE_ELECTIVE_REQUEST_SUCCESSFUL = "Your request has been received and is currently pending approval!\n" \ + "Use /request_elective to add another elective\n" \ + "Use /clear_electives to clear all pending requests for electives" +MESSAGE_NO_ELECTIVE_COURSES = "No elective courses available at the moment" + + +LOG_FILE_NAME = 'log' +LOG_MAX_SIZE_BYTES = 1024 * 1024 * 10 # 10 MB +LOG_NAME = 'logger' +LOG_BACKUP_COUNT = 1 +LOG_MESSAGE_FORMAT = "%(asctime)s :: %(message)s" +LOG_DATE_FORMAT = "%d.%m.%Y :: %H:%M:%S" + +REGISTER_START = "Register your account.\nUse /cancel to stop the process at any point in time." +REGISTER_PROMPT_FULLNAME = "Enter your full names:" +REGISTER_PROMPT_EMAIL = "Enter your historic inno-email address:\n(Don't bother if it isn't functional)" +REGISTER_SUCCESS = "Your registration was successfully.\nExplore the bots functionalities." +MESSAGE_REGISTER_ACCOUNT = "Register your accout using the /start command" +UPDATE_PROFILE = "Modify profile info 📒" +UPDATE_PROFILE_START = "Update your profile info.\nUse /cancel to stop the process at any point in time." +UPDATE_PROFILE_SUCCESS = "Your profile update went successfully.\nExplore the bots functionalities." + + +MESSAGE_NO_MULTIPLE_PASS_REQUEST = "You are not allowed to have multiple pending university pass requests" + +# PROFILE +CLEAR_HISTORY = "Clear request history 📜" + + +# ELECTIVE + +REQUEST_ELECTIVE = "Select an elective?" +CLEARED_ELECTIVE = "All pending requests for electives have been successfully removed.\n Use /request_elective to create new request for electives" + + +HEADER_NOW = "\n" +HEADER_WEEK = "\n" +HEADER_NEXT = "\n" +HEADER_NO_NEXT_LESSONS = " 🗽" +HEADER_SEPARATOR = "\n" +HEADER_REMIND = "⏰\n" + + +MESSAGE_YES = "Yes 🙋" +MESSAGE_NO = "No 🙅" + +MESSAGE_REMIND_SETTINGS_SAVED = "Your remind settings have been saved successfully!" + + +# REQUEST PASS +APPROVE_REQUEST = "Approve ✅" +REJECT_REQUEST = "Reject ❌" + +REQUEST_PASS = "Requesting a pass:\nAlone - simple pass for one person (you).\nWith company - pass for 2 or more people." +REQUEST_NUMBER_VISITORS = "How many individuals in total will be visiting?" +REQUEST_DATE = "Enter the date you wish to visit in the format (DD/MM)? \nUniversity passes are issued Monday - Friday, 9:00 - 18:00\n\n" + \ + "Use /volunteer to schedule urgent or impromptu visits." +REQUEST_VISITOR_NAMES = "Enter fullnames of each visitor all in one message.(excluding your name)" +REQUEST_PASS_SENT = "Please, do not forget to hold identification documents when visiting the University.\n\nYour pass request has been sent and is pending approval.\n\nUse /profile to know the status of your request." + + +CLEARED_PASS_REQUEST = "Your pending pass request has been successfully cancelled.\nUse /request_pass to create new pass request." + +REQ_PASS_SIMPLE = "Alone 🧑" +REQ_PASS_EXTRA = "With company 👪" + +# REQUEST VOLUNTEER +VOLUNTEER_LIST = [498255810] +CAN_HANDLE_REQUEST = "I will handle request" +CANNOT_HANDLE_REQUEST = "I can not handle request" +VOLUNTEER_REQUEST_SENT = "Your request for a volunteer has been sent. The first available volunteer will reach out to you via telegram.\n\nIf no response, please send new volunteer request in 15mins." + + +ALUMNI_OFFICE_LIST = [498255810] + + +DEVELOPER_LIST = [498255810] +ADMIN_LIST = [498255810] +SUPERADMIN_LIST = [498255810] + +# DONATION + +DONATION_MESSAGE = ''' +*КАРТОЧКА ПРЕДПРИЯТИЯ* + +*Полное наименование*: +Автономная некоммерческая организация высшего образования «Университет Иннополис» + +*Сокращенное наименование*: +АНО ВО «Университет Иннополис» + +*Директор*: +Семенихин Кирилл Владимирович + +*Главный бухгалтер*: +Симонова Лилия Вахитовна + +*ОГРН*: 1121600006142 + +*ИНН*: 1655258235 + +*КПП*: 161501001 + +*ОКПО*: 26762138 + +*Адрес местонахождения Организации*: +420500, Республика Татарстан, г\. Иннополис, ул\. Университетская, д\.1 + +*Почтовый адрес*: +420500, Республика Татарстан, г\. Иннополис, ул\. Университетская, д\.1 + +*Расчетный счет*: 40703810062000000497 + +*Банк*: ОТДЕЛЕНИЕ N8610 СБЕРБАНКА РОССИИ Г\. КАЗАНЬ + +*БИК*: 049205603 + +*Корреспондентский счет*: 30101810600000000603 + +''' +# write action that the user should take as follow up. Simple successful actions are not enough +# Feedback by Stas diff --git a/Backend/app/telegram/donation_profile_handlers.py b/Backend/app/telegram/donation_profile_handlers.py new file mode 100644 index 0000000..c1225ec --- /dev/null +++ b/Backend/app/telegram/donation_profile_handlers.py @@ -0,0 +1,130 @@ +from app.telegram.core_handlers import bot, log, main_markup +from app.telegram import data, controller +from telebot.types import ReplyKeyboardMarkup, InlineKeyboardButton, InlineKeyboardMarkup + + +MODULE_NAME = "DONATION_PROFILE" + + +def attach_donation_profile_module(): + fullname = None + + @bot.message_handler(commands=['donate']) + @bot.message_handler(regexp=f"^{data.TEXT_BUTTON_DONATE}$") + def donate(message): + log(MODULE_NAME, message) + print(f"donation link pressed by {message.from_user.id}") + user = controller.get_user(message.from_user.id) + if not user: + bot.send_message( + message.chat.id, data.MESSAGE_REGISTER_ACCOUNT, reply_markup=main_markup) + return + bot.send_message( + message.chat.id, data.DONATION_MESSAGE, reply_markup=main_markup, parse_mode="MarkdownV2") + + def handle_modify_profile_response(message): + if message.data == 'UPDATE_PROFILE': + bot.send_message(message.from_user.id, data.UPDATE_PROFILE_START, reply_markup=main_markup) + msg = bot.send_message(message.from_user.id, data.REGISTER_PROMPT_FULLNAME, + reply_markup=main_markup) + bot.register_next_step_handler(msg, process_modify_fullname_step) + if message.data == "CLEAR_HISTORY": + bot.edit_message_text(message_id=message.message.id, chat_id=message.from_user.id, + text=message.message.text, reply_markup=InlineKeyboardMarkup()) + controller.clear_request_history(message.from_user.id) + + def process_modify_fullname_step(message): + log(MODULE_NAME, message) + if not message.text: + bot.send_message(message.chat.id, data.MESSAGE_ERROR, + reply_markup=main_markup) + return + if message.text == "/cancel": + bot.send_message(message.chat.id, data.MESSAGE_CANCEL, + reply_markup=main_markup) + return + global fullname + fullname = message.text + msg = bot.send_message(message.chat.id, data.REGISTER_PROMPT_EMAIL, + reply_markup=main_markup) + bot.register_next_step_handler(msg, process_modify_email_step) + + def process_modify_email_step(message): + log(MODULE_NAME, message) + if not message.text: + bot.send_message(message.chat.id, data.MESSAGE_ERROR, + reply_markup=main_markup) + return + if message.text == "/cancel": + bot.send_message(message.chat.id, data.MESSAGE_CANCEL, + reply_markup=main_markup) + return + email = message.text + global fullname + controller.update_user(message.from_user.id, email, fullname, message.from_user.username) + bot.send_message(message.chat.id, data.UPDATE_PROFILE_SUCCESS, + reply_markup=main_markup) + + + @bot.message_handler(commands=['profile']) + @bot.message_handler(regexp=f"^{data.TEXT_BUTTON_PROFILE}$") + @bot.callback_query_handler(handle_modify_profile_response) + def view_profile(message): + log(MODULE_NAME, message) + print(f"USER {message.from_user.id} wants to see profile") + user = controller.get_full_user(message.from_user.id) + if not user: + bot.send_message( + message.chat.id, data.MESSAGE_REGISTER_ACCOUNT, reply_markup=main_markup) + return + requests = controller.get_requests(message.from_user.id) + display_request = list( + map(lambda x: controller.print_request(x), requests)) + course_abbrevations = list(map(lambda x: x.name, user.courses)) + + reply = f"Name: {user.fullnames}\nEmail: {user.email}" + \ + f"\n\nRequest Status:\n{''.join(display_request) if requests else 'NO REQUESTS'}" + \ + f"\nApproved Courses: {', '.join(course_abbrevations) if user.courses else 'NO COURSES'}" + + keyboard = [ + [ + InlineKeyboardButton( + data.UPDATE_PROFILE, callback_data="UPDATE_PROFILE") + ], + [ + InlineKeyboardButton( + data.CLEAR_HISTORY, callback_data="CLEAR_HISTORY") + ] + ] + reply_markup = InlineKeyboardMarkup(keyboard) + + bot.send_message(message.chat.id, reply, reply_markup=reply_markup) + + def remind_configuration(message): + log(MODULE_NAME, message) + if message.text == '/config_remind': + print(f"CONFIG REMIND pressed by {message.from_user.id}") + markup = ReplyKeyboardMarkup(True, False) + markup.add(data.MESSAGE_YES, data.MESSAGE_NO) + msg = bot.send_message( + message.chat.id, data.REQUEST_REMINDERS, reply_markup=markup) + bot.register_next_step_handler(msg, process_reminders_step) + + def process_reminders_step(message): + log(MODULE_NAME, message) + if not message.text: + bot.send_message(message.chat.id, data.MESSAGE_ERROR, + reply_markup=main_markup) + return + user_id = message.from_user.id + print(f"{message.text} pressed by {message.from_user.id}") + if message.text == data.MESSAGE_YES: + controller.set_reminder_on(user_id) + elif message.text == data.MESSAGE_NO: + controller.set_reminder_off(user_id) + else: + bot.send_message(message.chat.id, data.MESSAGE_ERROR, + reply_markup=main_markup) + return + bot.send_message( + message.chat.id, data.MESSAGE_SETTINGS_SAVED, reply_markup=main_markup) diff --git a/Backend/app/telegram/init.py b/Backend/app/telegram/init.py new file mode 100644 index 0000000..b5036dd --- /dev/null +++ b/Backend/app/telegram/init.py @@ -0,0 +1,18 @@ +from app.telegram.core_handlers import attach_core_module, compose_attached_modules +from app.telegram.request_pass_handlers import attach_request_pass_module +from app.telegram.donation_profile_handlers import attach_donation_profile_module +from app.telegram.course_handlers import attach_elective_module +from app.telegram.admin.handlers import attach_admin_module + + +def setup_telegram_bot(): + + # attach required modules + attach_core_module() + attach_request_pass_module() + attach_donation_profile_module() + attach_elective_module() + attach_admin_module() + + # compose modules and start listening + compose_attached_modules() diff --git a/Backend/app/telegram/request_pass_handlers.py b/Backend/app/telegram/request_pass_handlers.py new file mode 100644 index 0000000..413bc43 --- /dev/null +++ b/Backend/app/telegram/request_pass_handlers.py @@ -0,0 +1,266 @@ +from app.telegram.core_handlers import bot, log, main_markup +from app.telegram import data, controller +from telebot.types import InlineKeyboardButton, InlineKeyboardMarkup + +MODULE_NAME = "REQUEST_PASS" + + +def attach_request_pass_module(): + number_of_visitors = None + requested_date = None + + def handle_request_pass(message): + if message.data == 'APPROVE_REQUEST': + request_id = message.message.text.split('[')[1].split(']')[0] + print(request_id) + request = controller.approve_request(request_id) + request_result = controller.print_request_result(request) + bot.send_message(request.user_id, request_result, reply_markup=main_markup) + request_text = f"{message.message.text}\n\nStaff with telegram alias @{message.from_user.username} APPROVED PASS REQUEST." + for id in data.ALUMNI_OFFICE_LIST: + try: + bot.edit_message_text( + message_id=message.message.id, chat_id=id, text=request_text, reply_markup=InlineKeyboardMarkup()) + except: + print(f"Error happened while sending message to {id}") + continue + elif message.data == "REJECT_REQUEST": + request_id = message.message.text.split('[')[1].split(']')[0] + print(request_id) + request = controller.reject_request(request_id) + request_result = controller.print_request_result(request) + bot.send_message(request.user_id, request_result, reply_markup=main_markup) + request_text = f"{message.message.text}\n\nStaff with telegram alias @{message.from_user.username} REJECTED PASS REQUEST." + for id in data.ALUMNI_OFFICE_LIST: + try: + bot.edit_message_text( + message_id=message.message.id, chat_id=id, text=request_text, reply_markup=InlineKeyboardMarkup()) + except: + print( + f"Error happened while sending message to {id}") + continue + elif message.data == "REQ_PASS_SIMPLE": + request_text = f"{message.message.text}\n\nSimple pass request" + bot.edit_message_text(message_id=message.message.id, chat_id=message.from_user.id, text=request_text, reply_markup=InlineKeyboardMarkup()) + msg = bot.send_message(message.from_user.id, data.REQUEST_DATE, reply_markup=main_markup) + bot.register_next_step_handler(msg, process_simple_request_date_step) + + elif message.data == "REQ_PASS_EXTRA": + request_text = f"{message.message.text}\n\nCompany pass request" + bot.edit_message_text(message_id=message.message.id, chat_id=message.from_user.id, text=request_text, reply_markup=InlineKeyboardMarkup()) + msg = bot.send_message(message.from_user.id, data.REQUEST_NUMBER_VISITORS, reply_markup=main_markup) + bot.register_next_step_handler(msg, process_number_of_individuals_step) + + + @bot.message_handler(commands=['request_pass']) + @bot.message_handler(regexp=f"^{data.TEXT_BUTTON_PASS}$") + @bot.callback_query_handler(handle_request_pass) + def request_pass(message): + log(MODULE_NAME, message) + print(f"REQUEST PASS pressed by {message.from_user.id}") + user = controller.get_user(message.from_user.id) + if not user: + bot.send_message( + message.chat.id, data.MESSAGE_REGISTER_ACCOUNT, reply_markup=main_markup) + return + + keyboard = [ + [ + InlineKeyboardButton( + data.REQ_PASS_SIMPLE, callback_data="REQ_PASS_SIMPLE") + ], + [ + InlineKeyboardButton( + data.REQ_PASS_EXTRA, callback_data="REQ_PASS_EXTRA") + ], + ] + reply_markup = InlineKeyboardMarkup(keyboard) + bot.send_message( + message.chat.id, data.REQUEST_PASS, reply_markup=reply_markup) + + def process_number_of_individuals_step(message): + if message.text == "/cancel": + bot.send_message(message.chat.id, data.MESSAGE_CANCEL, + reply_markup=main_markup) + return + + if not message.text: + bot.send_message(message.chat.id, data.MESSAGE_ERROR, + reply_markup=main_markup) + return + + global number_of_visitors + number_of_visitors = message.text + + msg = bot.send_message( + message.chat.id, data.REQUEST_DATE, reply_markup=main_markup) + bot.register_next_step_handler( + msg, process_request_date_step) + + def process_request_date_step(message): + if message.text == "/cancel": + bot.send_message(message.chat.id, data.MESSAGE_CANCEL, + reply_markup=main_markup) + return + + if not message.text: + bot.send_message(message.chat.id, data.MESSAGE_ERROR, + reply_markup=main_markup) + return + + global requested_date + requested_date = message.text + + msg = bot.send_message( + message.chat.id, data.REQUEST_VISITOR_NAMES, reply_markup=main_markup) + bot.register_next_step_handler( + msg, process_visitor_names_step) + + def process_visitor_names_step(message): + if message.text == "/cancel": + bot.send_message(message.chat.id, data.MESSAGE_CANCEL, + reply_markup=main_markup) + return + + if not message.text: + bot.send_message(message.chat.id, data.MESSAGE_ERROR, + reply_markup=main_markup) + return + user = controller.get_user(message.from_user.id) + p_requests = controller.get_pending_pass_request(message.from_user.id) + if len(p_requests) >= 1: + bot.send_message(message.chat.id, data.MESSAGE_NO_MULTIPLE_PASS_REQUEST, + reply_markup=main_markup) + return + + visitor_names = message.text + global number_of_visitors, requested_date + description = f"PASS REQUEST\n\nhandle: \n@{user.handle}\n\nEmail: \n{user.email}\n\n" + \ + f"Number of visitors: \n{number_of_visitors}\n\nRequested date: \n{requested_date}\n\nVisitor names: \n{user.fullnames}\n{visitor_names}" + request = controller.request_pass(description, message.from_user.id) + description = f"[{request.id}]\n\n{description}" + keyboard = [ + [ + InlineKeyboardButton( + data.APPROVE_REQUEST, callback_data="APPROVE_REQUEST") + ], + [ + InlineKeyboardButton( + data.REJECT_REQUEST, callback_data="REJECT_REQUEST") + ], + ] + reply_markup = InlineKeyboardMarkup(keyboard) + + for id in data.ALUMNI_OFFICE_LIST: + try: + bot.send_message(id, description, reply_markup=reply_markup) + except: + print( + f"Error happened while sending pass request message to {id}") + continue + bot.send_message( + message.chat.id, data.REQUEST_PASS_SENT, reply_markup=main_markup) + + def process_simple_request_date_step(message): + if message.text == "/cancel": + bot.send_message(message.chat.id, data.MESSAGE_CANCEL, + reply_markup=main_markup) + return + + if not message.text: + bot.send_message(message.chat.id, data.MESSAGE_ERROR, + reply_markup=main_markup) + return + user = controller.get_user(message.from_user.id) + p_requests = controller.get_pending_pass_request(message.from_user.id) + if len(p_requests) >= 1: + bot.send_message(message.chat.id, data.MESSAGE_NO_MULTIPLE_PASS_REQUEST, + reply_markup=main_markup) + return + + requested_date = message.text + description = f"PASS REQUEST\n\nhandle: \n@{user.handle}\n\nEmail: \n{user.email}\n\n" + \ + f"Number of visitors: 1\n\nRequested date: \n{requested_date}\n\nVisitor names: \n{user.fullnames}" + request = controller.request_pass(description, message.from_user.id) + description = f"[{request.id}]\n\n{description}" + keyboard = [ + [ + InlineKeyboardButton( + data.APPROVE_REQUEST, callback_data="APPROVE_REQUEST") + ], + [ + InlineKeyboardButton( + data.REJECT_REQUEST, callback_data="REJECT_REQUEST") + ], + ] + reply_markup = InlineKeyboardMarkup(keyboard) + + for id in data.ALUMNI_OFFICE_LIST: + try: + bot.send_message(id, description, reply_markup=reply_markup) + except: + print( + f"Error happened while sending pass request message to {id}") + continue + bot.send_message( + message.chat.id, data.REQUEST_PASS_SENT, reply_markup=main_markup) + + @bot.message_handler(commands=['cancel_pass']) + def cancel_pass(message): + log(MODULE_NAME, message) + print(f"DELETE PASS pressed by {message.from_user.id}") + requests = controller.get_pending_pass_request( + message.from_user.id) + + if not requests: + bot.send_message( + message.chat.id, "No pending pass request", reply_markup=main_markup) + return + controller.delete_pending_pass_request(message.from_user.id) + bot.send_message( + message.chat.id, data.CLEARED_PASS_REQUEST, reply_markup=main_markup) + + def handle_volunteer_response(message): + if message.data == 'CAN_HANDLE_REQUEST': + user_id = message.message.text.split('[')[1].split(']')[0] + response_user = f"User with telegram alias @{message.from_user.username} is available and has volunteered to assist you. Please, write him immediately. Thanks for your patience." + bot.send_message(user_id, response_user, reply_markup=main_markup) + + request_text = f"{message.message.text}\n\nUser with telegram alias @{message.from_user.username} is attending to the volunteer request. Thanks for being a volunteer." + for id in data.VOLUNTEER_LIST: + try: + bot.edit_message_text( + message_id=message.message.id, chat_id=id, text=request_text, reply_markup=InlineKeyboardMarkup()) + except: + print( + f"Error happened while sending volunteer message to {id}") + continue + + @bot.message_handler(commands=['volunteer']) + @bot.callback_query_handler(handle_volunteer_response) + def request_volunteer(message): + log(MODULE_NAME, message) + print(f"REQUEST VOLUNTEER {message.from_user.id}") + user = controller.get_user(message.from_user.id) + if not user: + bot.send_message( + message.chat.id, data.MESSAGE_REGISTER_ACCOUNT, reply_markup=main_markup) + return + + keyboard = [ + [ + InlineKeyboardButton( + data.CAN_HANDLE_REQUEST, callback_data="CAN_HANDLE_REQUEST") + ], + ] + reply_markup = InlineKeyboardMarkup(keyboard) + request_text = f"User with telegram alias @{message.from_user.username} - [{message.from_user.id}] is requesting a volunteer. Indicate if you can assist them." + for id in data.VOLUNTEER_LIST: + try: + bot.send_message(id, request_text, reply_markup=reply_markup) + except: + print( + f"Error happened while sending volunteer message to {id}") + continue + bot.send_message( + message.chat.id, data.VOLUNTEER_REQUEST_SENT, reply_markup=main_markup) diff --git a/Backend/app/templates/account_verification.html b/Backend/app/templates/account_verification.html new file mode 100644 index 0000000..1106012 --- /dev/null +++ b/Backend/app/templates/account_verification.html @@ -0,0 +1,180 @@ + + + + + + + + + +
+ + + + + + + + + + + + + + +
+ + + + + + +
+ + Moolax +
+
+ + + + + + + +
+ Verify your account so we know it's really you. +
+ + + + + + + +
+ To verify your account, copy the code below. The code will be + invalid in + 10 minutes. +
+ + + + + + + +
+ + + + + + +
+ {{verification_code}} +
+
+ + + + + + +
+ If you didn't request verification of your account, you can ignore + and + delete this email.
+ + + + + + + +
+ Moolax is a money transfer platform for those who wish to send money + internationally. Moolax abstracts all the complexity involved in + carrying out money transfers and presents its users with a seemless + experience.
+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ + twitter + + + instagram + + + facebook + +
+
+ 420500, Innopolis City, University Street
+ Republic of Tatarstan, Russian Federation
+
+
+ + + \ No newline at end of file diff --git a/Backend/app/templates/forgot_password.html b/Backend/app/templates/forgot_password.html new file mode 100644 index 0000000..f7618d7 --- /dev/null +++ b/Backend/app/templates/forgot_password.html @@ -0,0 +1,182 @@ + + + + + + + + + +
+ + + + + + + + + + + + + + +
+ + + + + + +
+ + Moolax +
+
+ + + + + + + +
+ Forgot your password? It happens to the best of us. +
+ + + + + + + +
+ To reset your password, click the button below. The link will be + invalid + in 2 hours. +
+ + + + + + + +
+ + + + + + +
+ Reset Your Password +
+
+ + + + + + +
+ If you do not want to change your password or didn't request a + reset, + you can ignore and delete this email.
+ + + + + + + +
+ Moolax is a money transfer platform for those who wish to send money + internationally. Moolax abstracts all the complexity involved in + carrying out money transfers and presents its users with a seemless + experience.
+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ + twitter + + + instagram + + + facebook + +
+
+ 420500, Innopolis City, University Street
+ Republic of Tatarstan, Russian Federation
+
+
+ + + + \ No newline at end of file diff --git a/Backend/app/utils/email_handler.py b/Backend/app/utils/email_handler.py new file mode 100644 index 0000000..8e3f4f7 --- /dev/null +++ b/Backend/app/utils/email_handler.py @@ -0,0 +1,32 @@ +from anyio import Path +from fastapi import BackgroundTasks +from fastapi_mail import FastMail, MessageSchema, ConnectionConfig +from app.config import settings + +config = ConnectionConfig( + MAIL_USERNAME=settings.mail_username, + MAIL_PASSWORD=settings.mail_password, + MAIL_FROM=settings.mail_from, + MAIL_PORT=settings.mail_port, + MAIL_SERVER=settings.mail_server, + MAIL_FROM_NAME=settings.mail_from_name, + MAIL_STARTTLS = True, + MAIL_SSL_TLS = False, + # MAIL_TLS=True, + # MAIL_SSL=False, + USE_CREDENTIALS=True, + VALIDATE_CERTS = True, + TEMPLATE_FOLDER= Path(__file__).parent.parent / 'templates' +) + + +def send_email(background_tasks: BackgroundTasks, subject: str, email_to: str, body: dict, template_name): + message = MessageSchema( + subject=subject, + recipients=[email_to], + template_body=body, + subtype='html', + ) + fm = FastMail(config) + background_tasks.add_task( + fm.send_message, message, template_name=template_name) \ No newline at end of file diff --git a/Backend/app/utils/hash.py b/Backend/app/utils/hash.py new file mode 100644 index 0000000..78cce1d --- /dev/null +++ b/Backend/app/utils/hash.py @@ -0,0 +1,10 @@ +from passlib.context import CryptContext + +pwd_ctx = CryptContext(schemes=["bcrypt"], deprecated="auto") + + +def hash_password(password: str): + return pwd_ctx.hash(password) + +def verify_password(plain_password, hashed_password): + return pwd_ctx.verify(plain_password, hashed_password) \ No newline at end of file diff --git a/Backend/app/utils/oa2.py b/Backend/app/utils/oa2.py new file mode 100644 index 0000000..78f4181 --- /dev/null +++ b/Backend/app/utils/oa2.py @@ -0,0 +1,18 @@ +from fastapi import HTTPException, status, Depends +from fastapi.security import OAuth2PasswordBearer +from app.db import db + +from app.utils.token import verify_access_token + + +oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/user/login") + +def get_current_user(token: str = Depends(oauth2_scheme)): + credentials_exception = HTTPException( + status_code = status.HTTP_401_UNAUTHORIZED, + detail="Could not validate credentials", + headers={"WWW-Authenticate": "bearer"} + ) + email = verify_access_token(token, credentials_exception=credentials_exception) + user = db.user.find_first(where={"email": email}) + return user \ No newline at end of file diff --git a/Backend/app/utils/token.py b/Backend/app/utils/token.py new file mode 100644 index 0000000..2b7d2fc --- /dev/null +++ b/Backend/app/utils/token.py @@ -0,0 +1,37 @@ +from jose import JWTError, jwt +from typing import Optional +from datetime import datetime, timedelta +import uuid +from ..config import settings + +SECRET_KEY = settings.secret_key +ALGORITHM = settings.algorithm +ACCESS_TOKEN_EXPIRE_MINUTES = int(settings.access_token_expire_minutes) + +def create_access_token(data: dict, expires_delta: Optional[timedelta] = None): + to_encode = data.copy() + if expires_delta: + expire = datetime.utcnow() + expires_delta + else: + expire = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES) + + to_encode.update({"exp": expire}) + encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM) + return encoded_jwt + +def verify_access_token(token: str, credentials_exception): + try: + payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) + email: str = payload.get("sub") + if email is None: + raise credentials_exception + except JWTError: + raise credentials_exception + + return email + +def generate_user_verification_code(): + unique = uuid.uuid1() + code = str(unique).split("-").pop(0) + return code + diff --git a/Backend/app/version.py b/Backend/app/version.py index c0586a1..63084c9 100644 --- a/Backend/app/version.py +++ b/Backend/app/version.py @@ -1,16 +1,17 @@ from fastapi import APIRouter -from app.api import transaction, user, auth, admin, file, country, landing +from app.api import user_api +from app.api import elective_course_api +from app.api import pass_request_api + +# from app.api import seedapi + router = APIRouter() def version_one(): - router.include_router(auth.router) - # router.include_router(user.router) - # router.include_router(country.router) - # router.include_router(transaction.router) - # router.include_router(landing.router) - # router.include_router(file.router) - # router.include_router(admin.router) + router.include_router(user_api.router) + router.include_router(pass_request_api.router) + router.include_router(elective_course_api.router) -version_one() \ No newline at end of file +version_one() diff --git a/Backend/log b/Backend/log new file mode 100644 index 0000000..24856f0 --- /dev/null +++ b/Backend/log @@ -0,0 +1 @@ +09.07.2023 :: 22:57:35 :: core :: Hardriive ::/start diff --git a/Backend/requirements.txt b/Backend/requirements.txt index ccaac45..7c2f222 100644 --- a/Backend/requirements.txt +++ b/Backend/requirements.txt @@ -1,26 +1,46 @@ +aiosmtplib==2.0.2 anyio==3.7.0 -astroid==2.3.3 +bcrypt==4.0.1 +blinker==1.6.2 +certifi==2023.5.7 +charset-normalizer==3.2.0 click==8.1.3 +dnspython==2.3.0 +ecdsa==0.18.0 +email-validator==1.3.1 exceptiongroup==1.1.1 -fastapi==0.98.0 +fastapi==0.99.0 +fastapi-mail==1.3.1 h11==0.14.0 +httpcore==0.17.2 httptools==0.5.0 +httpx==0.24.1 idna==3.4 -importlib-metadata==6.7.0 -isort==4.3.21 -lazy-object-proxy==1.4.3 -mccabe==0.6.1 -pydantic==1.10.9 -pylint==2.4.4 -python-dotenv==0.21.1 +Jinja2==3.1.2 +jose==1.0.0 +MarkupSafe==2.1.3 +multipart==0.2.4 +nodeenv==1.8.0 +passlib==1.7.4 +prisma==0.9.1 +pyasn1==0.5.0 +pydantic==1.10.10 +pyTelegramBotAPI==4.12.0 +python-dotenv==1.0.0 +python-jose==3.3.0 +python-multipart==0.0.6 PyYAML==6.0 +requests==2.31.0 +rsa==4.9 +six==1.16.0 sniffio==1.3.0 starlette==0.27.0 -typed-ast==1.4.1 -typing-extensions==4.6.3 +starlette-admin==0.10.0 +telebot==0.0.5 +tomlkit==0.11.8 +typing_extensions==4.7.0 +urllib3==2.0.3 uvicorn==0.22.0 uvloop==0.17.0 watchfiles==0.19.0 websockets==11.0.3 -wrapt==1.11.2 -zipp==3.15.0 From 4ee310db8c52433391c0e33021067b9a0b8d34ea Mon Sep 17 00:00:00 2001 From: Daniel Atonge Date: Wed, 12 Jul 2023 17:20:09 +0300 Subject: [PATCH 4/6] integrates alumni admin --- Backend/app/api/user_api.py | 49 +++++++++++++++++++++++++++++- Backend/app/main.py | 2 +- Backend/app/utils/email_handler.py | 5 +-- 3 files changed, 52 insertions(+), 4 deletions(-) diff --git a/Backend/app/api/user_api.py b/Backend/app/api/user_api.py index 1b8d274..b622bdb 100644 --- a/Backend/app/api/user_api.py +++ b/Backend/app/api/user_api.py @@ -1,7 +1,7 @@ from fastapi.security.oauth2 import OAuth2PasswordRequestForm from fastapi.encoders import jsonable_encoder -from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException, Response, status +from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException, Request, Response, status from app.utils.oa2 import get_current_user from ..schema import schemas @@ -153,3 +153,50 @@ def confirm_verification( db.user.update(where={"id":user.id}, data={"is_verified": True}) return Response(status_code=status.HTTP_200_OK) + + +from fastapi_sso.sso.generic import create_provider +from typing import Any, Callable, Dict, List, Optional, Type, Union +discovery = { + "authorization_endpoint": 'https://sso.university.innopolis.ru/adfs/oauth2/authorize', + "token_endpoint": "http://127.0.0.1:9001/api/v1/user/token_sso", + "userinfo_endpoint": "http://127.0.0.1:9001/api/v1/user/user_sso", +} +# https://moodle.innopolis.university/auth/oauth2/login.php?id=1&wantsurl=%2F&sesskey=bxqcQ7BJwf +# https://sso.university.innopolis.ru/adfs/oauth2/authorize/?client_id=c393d763-6d21-4f25-9e64-857b6822336c& +# response_type=code&redirect_uri=https%3A%2F%2Fmoodle.innopolis.university%2Fadmin%2Foauth2callback.php& +# state=%2Fauth%2Foauth2%2Flogin.php%3Fwantsurl%3Dhttps%253A%252F%252F + +# moodle.innopolis.university%252F%26sesskey%3DEfWRDuEBqD%26id%3D1&scope=openid%20profile%20email%20allatclaims& +# response_mode=form_post +SSOProvider = create_provider(name="oidc", discovery_document=discovery) +sso = SSOProvider( + client_id="c393d763-6d21-4f25-9e64-857b6822336c", + client_secret="secret", + redirect_uri="http://127.0.0.1:9001/api/v1/user/callback", + allow_insecure_http=True, + scope=["openid"], + ) + +@router.get("/login_sso") +async def login_with_sso(): + print("login_sso") + print(sso) + return await sso.get_login_redirect() + +@router.get("/token_sso") +def token_callback_with_sso(): + print("token_sso") + pass + +@router.get("/user_sso") +def user_callback_with_sso(): + print("user_sso") + pass + +@router.get("/callback") +async def authentication_callback_with_sso(request: Request): + print("callback", request) + user = await sso.verify_and_process(request) + print(user) + pass \ No newline at end of file diff --git a/Backend/app/main.py b/Backend/app/main.py index 37009e6..a76557d 100644 --- a/Backend/app/main.py +++ b/Backend/app/main.py @@ -16,7 +16,7 @@ version="1.0", ) -origins = ['*'] +origins = ['http://localhost:3000'] app.add_middleware( CORSMiddleware, diff --git a/Backend/app/utils/email_handler.py b/Backend/app/utils/email_handler.py index 8e3f4f7..c03550b 100644 --- a/Backend/app/utils/email_handler.py +++ b/Backend/app/utils/email_handler.py @@ -7,7 +7,7 @@ MAIL_USERNAME=settings.mail_username, MAIL_PASSWORD=settings.mail_password, MAIL_FROM=settings.mail_from, - MAIL_PORT=settings.mail_port, + MAIL_PORT=int(settings.mail_port), MAIL_SERVER=settings.mail_server, MAIL_FROM_NAME=settings.mail_from_name, MAIL_STARTTLS = True, @@ -15,7 +15,7 @@ # MAIL_TLS=True, # MAIL_SSL=False, USE_CREDENTIALS=True, - VALIDATE_CERTS = True, + # VALIDATE_CERTS = True, TEMPLATE_FOLDER= Path(__file__).parent.parent / 'templates' ) @@ -27,6 +27,7 @@ def send_email(background_tasks: BackgroundTasks, subject: str, email_to: str, b template_body=body, subtype='html', ) + print(config) fm = FastMail(config) background_tasks.add_task( fm.send_message, message, template_name=template_name) \ No newline at end of file From 9a74401cc1c7e152c87e5a2a1f5ed7946a606afe Mon Sep 17 00:00:00 2001 From: Daniel Atonge Date: Fri, 14 Jul 2023 14:48:03 +0300 Subject: [PATCH 5/6] improves api documentation --- Backend/app/api/elective_course_api.py | 11 +++++++++-- Backend/app/api/pass_request_api.py | 2 +- Backend/app/api/user_api.py | 1 + Backend/app/schema/schemas.py | 1 + Backend/log | 5 +++++ 5 files changed, 17 insertions(+), 3 deletions(-) diff --git a/Backend/app/api/elective_course_api.py b/Backend/app/api/elective_course_api.py index 2b0ea68..9e1ecf5 100644 --- a/Backend/app/api/elective_course_api.py +++ b/Backend/app/api/elective_course_api.py @@ -1,5 +1,5 @@ from typing import List -from fastapi import APIRouter, Depends, status +from fastapi import APIRouter, Depends, status, HTTPException from app.db import db from app.utils.oa2 import get_current_user from ..schema import schemas @@ -14,7 +14,7 @@ def get_all_elective_courses(cur_user:schemas.UserOutput = Depends(get_current_u @router.get("/booked") def get_booked_elective_courses(cur_user:schemas.UserOutput = Depends(get_current_user)): - courses = db.courserequest.find_many(where={"user_id":cur_user.id}) + courses = db.courserequest.find_many(where={"user_id":cur_user.id}, include={"elective_course": True}) return courses @router.post("/", response_model=schemas.ElectiveCourse, status_code=status.HTTP_201_CREATED) @@ -31,6 +31,13 @@ def create_elective_course(course: schemas.ElectiveCourse, cur_user:schemas.User @router.post("/request", status_code=status.HTTP_201_CREATED) def request_elective_course(course_id: str, cur_user:schemas.UserOutput = Depends(get_current_user)): user_id = cur_user.id + found_elective = db.electivecourse.find_unique(where={"id": course_id}) + if not found_elective: + raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Course with this Id doesn't exist") + + already_being_processed = db.courserequest.find_first(where={"user_id": user_id, "course_id": course_id, "status": "PENDING"}) + if already_being_processed: + raise HTTPException(status_code=status.HTTP_406_NOT_ACCEPTABLE, detail="Your request is already being processed. Be patient") created_elective_request = db.courserequest.create(data={ "user_id": user_id, "course_id": course_id diff --git a/Backend/app/api/pass_request_api.py b/Backend/app/api/pass_request_api.py index 2b9042a..5f2778f 100644 --- a/Backend/app/api/pass_request_api.py +++ b/Backend/app/api/pass_request_api.py @@ -26,4 +26,4 @@ def order_pass(pass_request: schemas.OrderPassRequest, cur_user:schemas.UserOutp "guest_info": guest_info }) - return {"status": status.HTTP_201_CREATED, "detail": "Successfully created pass order"} \ No newline at end of file + return {"status": status.HTTP_201_CREATED, "detail": "Successfully created pass order", "data": requested_pass} \ No newline at end of file diff --git a/Backend/app/api/user_api.py b/Backend/app/api/user_api.py index b622bdb..d3a4b3c 100644 --- a/Backend/app/api/user_api.py +++ b/Backend/app/api/user_api.py @@ -50,6 +50,7 @@ def create_alumni_account(user_to_create: schemas.SignUpUser): encrypted_password = hash.hash_password(password) db.user.create(data={ + "name": user_to_create.name, "email": new_user_email, "password": encrypted_password }) diff --git a/Backend/app/schema/schemas.py b/Backend/app/schema/schemas.py index dbc273d..42e7fbf 100644 --- a/Backend/app/schema/schemas.py +++ b/Backend/app/schema/schemas.py @@ -27,6 +27,7 @@ class LogInUser(BaseModel): class SignUpUser(BaseModel): + name: str email: EmailStr password: str confirm_password: str diff --git a/Backend/log b/Backend/log index 24856f0..b9d90b0 100644 --- a/Backend/log +++ b/Backend/log @@ -1 +1,6 @@ 09.07.2023 :: 22:57:35 :: core :: Hardriive ::/start +14.07.2023 :: 12:58:44 :: DONATION_PROFILE :: Hardriive ::DONATE💰 +14.07.2023 :: 12:58:48 :: core :: Hardriive ::/start +14.07.2023 :: 12:59:03 :: core :: Hardriive ::Daniel ATONGE +14.07.2023 :: 12:59:27 :: core :: Hardriive ::d.atonge@innopolis.university +14.07.2023 :: 12:59:35 :: DONATION_PROFILE :: Hardriive ::DONATE💰 From b3f76461f07e0536ee7f1fb342c2e94793d0ae96 Mon Sep 17 00:00:00 2001 From: Daniel Atonge Date: Sun, 16 Jul 2023 22:05:25 +0300 Subject: [PATCH 6/6] combining frontend and backend repositories --- .gitignore | 15 +- Backend/log | 6 - CHANGELOG.md | 88 + Frontend/Dockerfile => Dockerfile | 0 Frontend/.dockerignore | 4 - Frontend/.eslintrc.json | 3 - Frontend/.gitignore | 36 - Frontend/README.md | 14 - Frontend/next.config.js | 34 - Frontend/package-lock.json | 5970 ----------------- Frontend/package.json | 35 - Frontend/postcss.config.js | 6 - Frontend/requirements.txt | 2 - Frontend/src/components/features/avatar.tsx | 11 - .../src/components/features/editprofile.tsx | 234 - Frontend/src/components/layout/authLayout.tsx | 16 - Frontend/src/components/layout/header.tsx | 17 - Frontend/src/components/layout/leftBar.tsx | 75 - Frontend/src/components/layout/mainLayout.tsx | 14 - Frontend/src/components/layout/rightBar.tsx | 89 - .../src/components/modals/error.modal.tsx | 25 - .../src/components/modals/success.modal.tsx | 25 - Frontend/src/constants/index.tsx | 1 - Frontend/src/context/store.tsx | 48 - Frontend/src/interfaces/index.tsx | 4 - Frontend/src/lib/profileData.lib.tsx | 28 - Frontend/src/pages/_app.tsx | 8 - Frontend/src/pages/_document.tsx | 25 - Frontend/src/pages/account-profile/index.tsx | 185 - Frontend/src/pages/confirmation/index.tsx | 108 - Frontend/src/pages/course/index.tsx | 208 - Frontend/src/pages/dashboard/index.tsx | 30 - Frontend/src/pages/donation/index.tsx | 49 - Frontend/src/pages/index.tsx | 63 - Frontend/src/pages/login/index.tsx | 134 - Frontend/src/pages/pass/index.tsx | 139 - Frontend/src/pages/profile/index.tsx | 136 - Frontend/src/pages/register/index.tsx | 152 - Frontend/src/schemaValidation/index.tsx | 47 - Frontend/src/styles/form.module.css | 28 - Frontend/src/styles/globals.css | 16 - Frontend/src/styles/image.module.css | 89 - Frontend/src/utils/images/DynamicView.jpg | Bin 56634 -> 0 bytes Frontend/src/utils/images/Logo.png | Bin 1604 -> 0 bytes Frontend/src/utils/images/Logo_Alumni.png | Bin 1425 -> 0 bytes Frontend/tailwind.config.js | 15 - LICENSE.md | 21 + README.md | 9 +- .../app => app}/api/elective_course_api.py | 0 {Backend/app => app}/api/pass_request_api.py | 0 {Backend/app => app}/api/user_api.py | 0 {Backend/app => app}/config.py | 0 {Backend/app => app}/db.py | 0 {Backend/app => app}/main.py | 0 {Backend/app => app}/prisma/schema.prisma | 0 {Backend/app => app}/schema/schemas.py | 0 .../app => app}/telegram/admin/controller.py | 0 {Backend/app => app}/telegram/admin/data.py | 0 .../app => app}/telegram/admin/handlers.py | 0 {Backend/app => app}/telegram/controller.py | 0 .../app => app}/telegram/core_handlers.py | 0 .../app => app}/telegram/course_handlers.py | 0 {Backend/app => app}/telegram/data.py | 0 .../telegram/donation_profile_handlers.py | 0 {Backend/app => app}/telegram/init.py | 0 .../telegram/request_pass_handlers.py | 0 .../templates/account_verification.html | 0 .../templates/forgot_password.html | 0 {Backend/app => app}/utils/email_handler.py | 0 {Backend/app => app}/utils/hash.py | 0 {Backend/app => app}/utils/oa2.py | 0 {Backend/app => app}/utils/token.py | 0 {Backend/app => app}/version.py | 0 jsconfig.json | 5 + next-env.d.ts | 5 + next.config.js | 11 + package-lock.json | 5714 +++++++++++++++- package.json | 46 +- public/android-chrome-192x192.png | Bin 0 -> 2567 bytes public/android-chrome-512x512.png | Bin 0 -> 13075 bytes public/apple-touch-icon.png | Bin 0 -> 2216 bytes .../assets/avatars/avatar-alcides-antonio.png | Bin 0 -> 89929 bytes public/assets/avatars/avatar-anika-visser.png | Bin 0 -> 78371 bytes public/assets/avatars/avatar-cao-yu.png | Bin 0 -> 94425 bytes .../assets/avatars/avatar-carson-darrin.png | Bin 0 -> 71807 bytes public/assets/avatars/avatar-chinasa-neo.png | Bin 0 -> 80027 bytes public/assets/avatars/avatar-fran-perez.png | Bin 0 -> 91386 bytes public/assets/avatars/avatar-iulia-albu.png | Bin 0 -> 81280 bytes .../assets/avatars/avatar-jane-rotanson.png | Bin 0 -> 73042 bytes public/assets/avatars/avatar-jie-yan-song.png | Bin 0 -> 94425 bytes public/assets/avatars/avatar-marcus-finn.png | Bin 0 -> 88998 bytes public/assets/avatars/avatar-miron-vitold.png | Bin 0 -> 78669 bytes .../assets/avatars/avatar-nasimiyu-danai.png | Bin 0 -> 79765 bytes public/assets/avatars/avatar-neha-punita.png | Bin 0 -> 92152 bytes public/assets/avatars/avatar-omar-darboe.png | Bin 0 -> 72971 bytes .../assets/avatars/avatar-penjani-inyene.png | Bin 0 -> 79568 bytes public/assets/avatars/avatar-seo-hyeon-ji.png | Bin 0 -> 82157 bytes .../avatars/avatar-siegbert-gottfried.png | Bin 0 -> 75493 bytes .../assets/donations}/qr-code.jpg | Bin public/assets/errors/error-401.png | Bin 0 -> 189456 bytes public/assets/errors/error-404.png | Bin 0 -> 169567 bytes public/assets/errors/error-500.png | Bin 0 -> 215288 bytes public/assets/innopolis-alumni-photo.jpeg | Bin 0 -> 47258 bytes .../assets/logos/innopolis-alumni-photo.jpeg | Bin 0 -> 47258 bytes public/assets/logos/innopolis-favicon.png | Bin 0 -> 474 bytes public/assets/logos/innopolis-logo.png | Bin 0 -> 15133 bytes public/assets/logos/logo-dropbox.png | Bin 0 -> 6275 bytes public/assets/logos/logo-github.png | Bin 0 -> 6427 bytes public/assets/logos/logo-lyft.png | Bin 0 -> 4899 bytes public/assets/logos/logo-medium.png | Bin 0 -> 3464 bytes public/assets/logos/logo-slack.png | Bin 0 -> 9930 bytes public/assets/logos/logo-squarespace.png | Bin 0 -> 6840 bytes .../assets/overview}/alumni.png | Bin .../assets/overview/coins.png | Bin .../assets/overview/hand.png | Bin .../Hat.png => public/assets/overview/hat.png | Bin .../assets/overview/lock.png | Bin public/favicon-16x16.png | Bin 0 -> 253 bytes public/favicon-32x32.png | Bin 0 -> 354 bytes public/favicon.ico | Bin 0 -> 15406 bytes public/manifest.json | 15 + public/site.webmanifest | 1 + Backend/requirements.txt => requirements.txt | 7 +- src/api/index.js | 141 + src/api/sendRequest.js | 35 + src/components/chart.js | 9 + src/components/logo.js | 26 + src/components/scrollbar.js | 4 + src/components/severity-pill.js | 58 + src/contexts/auth-context.js | 203 + src/guards/auth-guard.js | 57 + src/hocs/with-auth-guard.js | 7 + src/hooks/use-auth.js | 4 + src/hooks/use-mocked-user.js | 10 + src/hooks/use-nprogress.js | 17 + src/hooks/use-popover.js | 26 + src/hooks/use-selection.js | 35 + .../admin-dashboard/account-popover.js | 71 + src/layouts/admin-dashboard/config.js | 59 + src/layouts/admin-dashboard/layout.js | 62 + src/layouts/admin-dashboard/side-nav-item.js | 92 + src/layouts/admin-dashboard/side-nav.js | 164 + src/layouts/admin-dashboard/top-nav.js | 98 + src/layouts/auth/layout.js | 116 + src/layouts/dashboard/account-popover.js | 71 + src/layouts/dashboard/config.js | 50 + src/layouts/dashboard/layout.js | 62 + src/layouts/dashboard/side-nav-item.js | 92 + src/layouts/dashboard/side-nav.js | 165 + src/layouts/dashboard/top-nav.js | 98 + src/pages/404.js | 80 + src/pages/_app.js | 55 + src/pages/_document.js | 105 + src/pages/admin/account.js | 64 + src/pages/admin/auth/login.js | 192 + src/pages/admin/donations.js | 74 + src/pages/admin/elective_requests.js | 264 + src/pages/admin/electives.js | 290 + src/pages/admin/index.js | 120 + src/pages/admin/pass_requests.js | 264 + src/pages/auth/login.js | 208 + src/pages/auth/register.js | 181 + src/pages/index.js | 82 + src/pages/make_donations.js | 81 + src/pages/manage_account.js | 66 + src/pages/manage_electives.js | 137 + src/pages/manage_pass.js | 83 + .../account/account-profile-details.js | 254 + src/sections/account/account-profile.js | 69 + src/sections/account/create-pass-request.js | 188 + .../account/elective-request-table.js | 123 + src/sections/account/pass-request-table.js | 123 + src/sections/account/settings-password.js | 76 + src/sections/customer/customers-search.js | 23 + src/sections/customer/customers-table.js | 156 + .../customer/request-elective-table.js | 283 + src/sections/donations/bank-details.js | 110 + .../donations/donation-information.js | 105 + src/sections/donations/pass-request-info.js | 58 + src/sections/donations/payment-qrcode.js | 43 + .../donations/suggest-donation-interest.js | 88 + src/sections/donations/upload-qrcode.js | 49 + .../donations/why-donate-innopolis.js | 59 + src/sections/overview/create-pass-request.js | 159 + .../overview/overview-feature-item.js | 57 + .../overview/overview-latest-products.js | 99 + .../overview/overview-latest-requests.js | 105 + src/theme/colors.js | 70 + src/theme/create-components.js | 301 + src/theme/create-palette.js | 33 + src/theme/create-shadows.js | 29 + src/theme/create-typography.js | 76 + src/theme/index.js | 31 + src/utils/apply-pagination.js | 3 + src/utils/create-emotion-cache.js | 5 + src/utils/create-resource-id.js | 5 + src/utils/get-initials.js | 6 + Frontend/tsconfig.json => tsconfig.json | 9 +- 198 files changed, 12545 insertions(+), 8494 deletions(-) delete mode 100644 Backend/log create mode 100644 CHANGELOG.md rename Frontend/Dockerfile => Dockerfile (100%) delete mode 100644 Frontend/.dockerignore delete mode 100644 Frontend/.eslintrc.json delete mode 100644 Frontend/.gitignore delete mode 100644 Frontend/README.md delete mode 100644 Frontend/next.config.js delete mode 100644 Frontend/package-lock.json delete mode 100644 Frontend/package.json delete mode 100644 Frontend/postcss.config.js delete mode 100644 Frontend/requirements.txt delete mode 100644 Frontend/src/components/features/avatar.tsx delete mode 100644 Frontend/src/components/features/editprofile.tsx delete mode 100644 Frontend/src/components/layout/authLayout.tsx delete mode 100644 Frontend/src/components/layout/header.tsx delete mode 100644 Frontend/src/components/layout/leftBar.tsx delete mode 100644 Frontend/src/components/layout/mainLayout.tsx delete mode 100644 Frontend/src/components/layout/rightBar.tsx delete mode 100644 Frontend/src/components/modals/error.modal.tsx delete mode 100644 Frontend/src/components/modals/success.modal.tsx delete mode 100644 Frontend/src/constants/index.tsx delete mode 100644 Frontend/src/context/store.tsx delete mode 100644 Frontend/src/interfaces/index.tsx delete mode 100644 Frontend/src/lib/profileData.lib.tsx delete mode 100644 Frontend/src/pages/_app.tsx delete mode 100644 Frontend/src/pages/_document.tsx delete mode 100644 Frontend/src/pages/account-profile/index.tsx delete mode 100644 Frontend/src/pages/confirmation/index.tsx delete mode 100644 Frontend/src/pages/course/index.tsx delete mode 100644 Frontend/src/pages/dashboard/index.tsx delete mode 100644 Frontend/src/pages/donation/index.tsx delete mode 100644 Frontend/src/pages/index.tsx delete mode 100644 Frontend/src/pages/login/index.tsx delete mode 100644 Frontend/src/pages/pass/index.tsx delete mode 100644 Frontend/src/pages/profile/index.tsx delete mode 100644 Frontend/src/pages/register/index.tsx delete mode 100644 Frontend/src/schemaValidation/index.tsx delete mode 100644 Frontend/src/styles/form.module.css delete mode 100644 Frontend/src/styles/globals.css delete mode 100644 Frontend/src/styles/image.module.css delete mode 100644 Frontend/src/utils/images/DynamicView.jpg delete mode 100644 Frontend/src/utils/images/Logo.png delete mode 100644 Frontend/src/utils/images/Logo_Alumni.png delete mode 100644 Frontend/tailwind.config.js create mode 100644 LICENSE.md mode change 100644 => 100755 README.md rename {Backend/app => app}/api/elective_course_api.py (100%) rename {Backend/app => app}/api/pass_request_api.py (100%) rename {Backend/app => app}/api/user_api.py (100%) rename {Backend/app => app}/config.py (100%) rename {Backend/app => app}/db.py (100%) rename {Backend/app => app}/main.py (100%) rename {Backend/app => app}/prisma/schema.prisma (100%) rename {Backend/app => app}/schema/schemas.py (100%) rename {Backend/app => app}/telegram/admin/controller.py (100%) rename {Backend/app => app}/telegram/admin/data.py (100%) rename {Backend/app => app}/telegram/admin/handlers.py (100%) rename {Backend/app => app}/telegram/controller.py (100%) rename {Backend/app => app}/telegram/core_handlers.py (100%) rename {Backend/app => app}/telegram/course_handlers.py (100%) rename {Backend/app => app}/telegram/data.py (100%) rename {Backend/app => app}/telegram/donation_profile_handlers.py (100%) rename {Backend/app => app}/telegram/init.py (100%) rename {Backend/app => app}/telegram/request_pass_handlers.py (100%) rename {Backend/app => app}/templates/account_verification.html (100%) rename {Backend/app => app}/templates/forgot_password.html (100%) rename {Backend/app => app}/utils/email_handler.py (100%) rename {Backend/app => app}/utils/hash.py (100%) rename {Backend/app => app}/utils/oa2.py (100%) rename {Backend/app => app}/utils/token.py (100%) rename {Backend/app => app}/version.py (100%) create mode 100644 jsconfig.json create mode 100644 next-env.d.ts create mode 100644 next.config.js create mode 100644 public/android-chrome-192x192.png create mode 100644 public/android-chrome-512x512.png create mode 100644 public/apple-touch-icon.png create mode 100644 public/assets/avatars/avatar-alcides-antonio.png create mode 100644 public/assets/avatars/avatar-anika-visser.png create mode 100644 public/assets/avatars/avatar-cao-yu.png create mode 100644 public/assets/avatars/avatar-carson-darrin.png create mode 100644 public/assets/avatars/avatar-chinasa-neo.png create mode 100644 public/assets/avatars/avatar-fran-perez.png create mode 100644 public/assets/avatars/avatar-iulia-albu.png create mode 100644 public/assets/avatars/avatar-jane-rotanson.png create mode 100644 public/assets/avatars/avatar-jie-yan-song.png create mode 100644 public/assets/avatars/avatar-marcus-finn.png create mode 100644 public/assets/avatars/avatar-miron-vitold.png create mode 100644 public/assets/avatars/avatar-nasimiyu-danai.png create mode 100644 public/assets/avatars/avatar-neha-punita.png create mode 100644 public/assets/avatars/avatar-omar-darboe.png create mode 100644 public/assets/avatars/avatar-penjani-inyene.png create mode 100644 public/assets/avatars/avatar-seo-hyeon-ji.png create mode 100644 public/assets/avatars/avatar-siegbert-gottfried.png rename {Frontend/src/utils/images => public/assets/donations}/qr-code.jpg (100%) create mode 100644 public/assets/errors/error-401.png create mode 100644 public/assets/errors/error-404.png create mode 100644 public/assets/errors/error-500.png create mode 100644 public/assets/innopolis-alumni-photo.jpeg create mode 100644 public/assets/logos/innopolis-alumni-photo.jpeg create mode 100644 public/assets/logos/innopolis-favicon.png create mode 100644 public/assets/logos/innopolis-logo.png create mode 100644 public/assets/logos/logo-dropbox.png create mode 100644 public/assets/logos/logo-github.png create mode 100644 public/assets/logos/logo-lyft.png create mode 100644 public/assets/logos/logo-medium.png create mode 100644 public/assets/logos/logo-slack.png create mode 100644 public/assets/logos/logo-squarespace.png rename {Frontend/src/utils/images => public/assets/overview}/alumni.png (100%) rename Frontend/src/utils/images/Coins.png => public/assets/overview/coins.png (100%) rename Frontend/src/utils/images/Hand.png => public/assets/overview/hand.png (100%) rename Frontend/src/utils/images/Hat.png => public/assets/overview/hat.png (100%) rename Frontend/src/utils/images/Lock.png => public/assets/overview/lock.png (100%) create mode 100644 public/favicon-16x16.png create mode 100644 public/favicon-32x32.png create mode 100644 public/favicon.ico create mode 100644 public/manifest.json create mode 100644 public/site.webmanifest rename Backend/requirements.txt => requirements.txt (90%) create mode 100644 src/api/index.js create mode 100644 src/api/sendRequest.js create mode 100644 src/components/chart.js create mode 100644 src/components/logo.js create mode 100644 src/components/scrollbar.js create mode 100644 src/components/severity-pill.js create mode 100644 src/contexts/auth-context.js create mode 100644 src/guards/auth-guard.js create mode 100644 src/hocs/with-auth-guard.js create mode 100644 src/hooks/use-auth.js create mode 100644 src/hooks/use-mocked-user.js create mode 100644 src/hooks/use-nprogress.js create mode 100644 src/hooks/use-popover.js create mode 100644 src/hooks/use-selection.js create mode 100644 src/layouts/admin-dashboard/account-popover.js create mode 100644 src/layouts/admin-dashboard/config.js create mode 100644 src/layouts/admin-dashboard/layout.js create mode 100644 src/layouts/admin-dashboard/side-nav-item.js create mode 100644 src/layouts/admin-dashboard/side-nav.js create mode 100644 src/layouts/admin-dashboard/top-nav.js create mode 100644 src/layouts/auth/layout.js create mode 100644 src/layouts/dashboard/account-popover.js create mode 100644 src/layouts/dashboard/config.js create mode 100644 src/layouts/dashboard/layout.js create mode 100644 src/layouts/dashboard/side-nav-item.js create mode 100644 src/layouts/dashboard/side-nav.js create mode 100644 src/layouts/dashboard/top-nav.js create mode 100644 src/pages/404.js create mode 100644 src/pages/_app.js create mode 100644 src/pages/_document.js create mode 100644 src/pages/admin/account.js create mode 100644 src/pages/admin/auth/login.js create mode 100644 src/pages/admin/donations.js create mode 100644 src/pages/admin/elective_requests.js create mode 100644 src/pages/admin/electives.js create mode 100644 src/pages/admin/index.js create mode 100644 src/pages/admin/pass_requests.js create mode 100644 src/pages/auth/login.js create mode 100644 src/pages/auth/register.js create mode 100644 src/pages/index.js create mode 100644 src/pages/make_donations.js create mode 100644 src/pages/manage_account.js create mode 100644 src/pages/manage_electives.js create mode 100644 src/pages/manage_pass.js create mode 100644 src/sections/account/account-profile-details.js create mode 100644 src/sections/account/account-profile.js create mode 100644 src/sections/account/create-pass-request.js create mode 100644 src/sections/account/elective-request-table.js create mode 100644 src/sections/account/pass-request-table.js create mode 100644 src/sections/account/settings-password.js create mode 100644 src/sections/customer/customers-search.js create mode 100644 src/sections/customer/customers-table.js create mode 100644 src/sections/customer/request-elective-table.js create mode 100644 src/sections/donations/bank-details.js create mode 100644 src/sections/donations/donation-information.js create mode 100644 src/sections/donations/pass-request-info.js create mode 100644 src/sections/donations/payment-qrcode.js create mode 100644 src/sections/donations/suggest-donation-interest.js create mode 100644 src/sections/donations/upload-qrcode.js create mode 100644 src/sections/donations/why-donate-innopolis.js create mode 100644 src/sections/overview/create-pass-request.js create mode 100644 src/sections/overview/overview-feature-item.js create mode 100644 src/sections/overview/overview-latest-products.js create mode 100644 src/sections/overview/overview-latest-requests.js create mode 100644 src/theme/colors.js create mode 100644 src/theme/create-components.js create mode 100644 src/theme/create-palette.js create mode 100644 src/theme/create-shadows.js create mode 100644 src/theme/create-typography.js create mode 100644 src/theme/index.js create mode 100644 src/utils/apply-pagination.js create mode 100644 src/utils/create-emotion-cache.js create mode 100644 src/utils/create-resource-id.js create mode 100644 src/utils/get-initials.js rename Frontend/tsconfig.json => tsconfig.json (87%) diff --git a/.gitignore b/.gitignore index 1bb661e..e8b2b98 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,9 @@ -Backend/**/__pycache__/ -Backend/**/.DS_Store/ -Frontend/node_modules/ -Backend/**/.env -Backend/venv -.DS_Store \ No newline at end of file +**/__pycache__/ +**/.DS_Store/ +node_modules/ +**/.env +venv +.DS_Store + +log +.next diff --git a/Backend/log b/Backend/log deleted file mode 100644 index b9d90b0..0000000 --- a/Backend/log +++ /dev/null @@ -1,6 +0,0 @@ -09.07.2023 :: 22:57:35 :: core :: Hardriive ::/start -14.07.2023 :: 12:58:44 :: DONATION_PROFILE :: Hardriive ::DONATE💰 -14.07.2023 :: 12:58:48 :: core :: Hardriive ::/start -14.07.2023 :: 12:59:03 :: core :: Hardriive ::Daniel ATONGE -14.07.2023 :: 12:59:27 :: core :: Hardriive ::d.atonge@innopolis.university -14.07.2023 :: 12:59:35 :: DONATION_PROFILE :: Hardriive ::DONATE💰 diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..f66e8ec --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,88 @@ +## v3.0.0 + +###### Feb 24, 2023 + +- Update dependencies +- Update design system +- Refactor components +- Replace authentication + +## v2.1.0 + +###### Sep 15, 2022 + +- Integrate Zalter Authentication +- Update dependencies + +## v2.0.0 + +###### Nov 8, 2021 + +- Migrate to Next.js +- Update design system + +# Change Log + +## v1.0.0 + +###### Aug 7, 2020 + +- Add `eslint` +- Add `Feather Icons` +- Add `Formik` for login/register pages +- Implement `react-router` v6 routing method +- Remove extra views +- Remove `node-sass` dependency +- Update all components to match the PRO version style +- Update dependencies +- Update folder structure to remove folder depth +- Update theme configuration + +## v0.4.0 + +###### Jul 24, 2019 + +- Adjust theme colors +- Implement `useStyle` hook instead of `withStyles` HOC +- Implement a custom Route component to wrap views in layouts +- Remove `services` and `data` folders, each component has its own data +- Remove unused `.scss` files from `assets` folder +- Replace `.jsx` with `.js` +- Replace Class Components with Function Components +- Replace custom components (Portlet) with Material-UI built-in components +- Replace dependency `classnames` with `clsx` +- Update dependencies +- Update the layout to match the PRO version + +## v0.3.0 + +###### May 13, 2019 + +- Implement `jsconfig.json` file and removed `.env` to match React v16.8.6 absolute paths +- Update chart styles and options +- Update Dashboard view top widgets styles and structure +- Update few icons to match @material-ui v4 updates +- Update React version to 16.8.6 to support React Hooks +- Update to @material-ui to 4.0.0-beta + +## v0.2.0 + +###### May 11, 2019 + +- Add docs for IE11 polyfill +- Fix `DisplayMode` component size, when used as a flex child it could grow/shrink +- Fix `ProductCard` component description height +- Fix `Typography` view responsiveness for small devices +- Fix charts responsiveness +- Remove "status" from `ProductCard` component since it was not part of released design +- Remove `auth` service folder since it won't be implemented for this version +- Remove `authGuard` since it won't be used in this version +- Remove unused components from shared components +- Remove unused scss from assets +- Update README.md + +## v0.1.0 + +###### May 2, 2019 + +### Initial commit diff --git a/Frontend/Dockerfile b/Dockerfile similarity index 100% rename from Frontend/Dockerfile rename to Dockerfile diff --git a/Frontend/.dockerignore b/Frontend/.dockerignore deleted file mode 100644 index 74b8ff5..0000000 --- a/Frontend/.dockerignore +++ /dev/null @@ -1,4 +0,0 @@ -package_lock.json -.next -node_modules -next-env.d.ts diff --git a/Frontend/.eslintrc.json b/Frontend/.eslintrc.json deleted file mode 100644 index aa0c77e..0000000 --- a/Frontend/.eslintrc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": ["next/core-web-vitals"] -} \ No newline at end of file diff --git a/Frontend/.gitignore b/Frontend/.gitignore deleted file mode 100644 index c87c9b3..0000000 --- a/Frontend/.gitignore +++ /dev/null @@ -1,36 +0,0 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -# dependencies -/node_modules -/.pnp -.pnp.js - -# testing -/coverage - -# next.js -/.next/ -/out/ - -# production -/build - -# misc -.DS_Store -*.pem - -# debug -npm-debug.log* -yarn-debug.log* -yarn-error.log* -.pnpm-debug.log* - -# local env files -.env*.local - -# vercel -.vercel - -# typescript -*.tsbuildinfo -next-env.d.ts diff --git a/Frontend/README.md b/Frontend/README.md deleted file mode 100644 index 668a460..0000000 --- a/Frontend/README.md +++ /dev/null @@ -1,14 +0,0 @@ -# Inno-alumni-portal frontend - -## How to run on local -1. Open a shell/command line in this folder -2. To `install` all packages (local to the repo) using `npm` - ```bash - npm install -3. To `build` the project for production - ```bash - npm run build -4. To `start` the project on development - ```bash - npm run dev - \ No newline at end of file diff --git a/Frontend/next.config.js b/Frontend/next.config.js deleted file mode 100644 index 02d53fe..0000000 --- a/Frontend/next.config.js +++ /dev/null @@ -1,34 +0,0 @@ -/** @type {import('next').NextConfig} */ -const nextConfig = { - reactStrictMode: true, - typescript: { - ignoreBuildErrors: true, - } -} - -module.exports = nextConfig - - -module.exports = { - images: { - dangerouslyAllowSVG: true, - contentSecurityPolicy: "default-src 'self'; script-src 'none'; sandbox;", - "baseUrl": "./src", - }, - typescript: { - ignoreBuildErrors: true, - }, - eslint: { - // Warning: This allows production builds to successfully complete even if - // your project has ESLint errors. - ignoreDuringBuilds: true, - }, - // async rewrites() { - // return [ - // { - // source: '/api/:path*', - // destination: 'http://alumni.pythonanywhere.com/:path*', - // }, - // ] - // }, -} diff --git a/Frontend/package-lock.json b/Frontend/package-lock.json deleted file mode 100644 index 9a1ed10..0000000 --- a/Frontend/package-lock.json +++ /dev/null @@ -1,5970 +0,0 @@ -{ - "name": "alumni-portal", - "version": "0.1.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "alumni-portal", - "version": "0.1.0", - "dependencies": { - "@next/font": "13.1.4", - "@types/node": "18.11.18", - "@types/react": "18.0.27", - "@types/react-dom": "18.0.10", - "axios": "^1.3.5", - "eslint-config-next": "13.1.4", - "formik": "^2.4.2", - "isomorphic-unfetch": "^4.0.2", - "next": "13.1.4", - "postcss-preset-env": "^8.0.1", - "react": "18.2.0", - "react-datepicker": "^4.11.0", - "react-dom": "18.2.0", - "react-icons": "^4.8.0", - "typescript": "4.9.4", - "yup": "^1.2.0" - }, - "devDependencies": { - "@types/react-datepicker": "^4.11.2", - "autoprefixer": "^10.4.13", - "postcss": "^8.4.21", - "tailwindcss": "^3.2.6" - } - }, - "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/runtime": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.5.tgz", - "integrity": "sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA==", - "dependencies": { - "regenerator-runtime": "^0.13.11" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@csstools/cascade-layer-name-parser": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@csstools/cascade-layer-name-parser/-/cascade-layer-name-parser-1.0.2.tgz", - "integrity": "sha512-xm7Mgwej/wBfLoK0K5LfntmPJzoULayl1XZY9JYgQgT29JiqNw++sLnx95u5y9zCihblzkyaRYJrsRMhIBzRdg==", - "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "@csstools/css-parser-algorithms": "^2.1.1", - "@csstools/css-tokenizer": "^2.1.1" - } - }, - "node_modules/@csstools/color-helpers": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-2.1.0.tgz", - "integrity": "sha512-OWkqBa7PDzZuJ3Ha7T5bxdSVfSCfTq6K1mbAhbO1MD+GSULGjrp45i5RudyJOedstSarN/3mdwu9upJE7gDXfw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "engines": { - "node": "^14 || ^16 || >=18" - } - }, - "node_modules/@csstools/css-calc": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-1.1.1.tgz", - "integrity": "sha512-Nh+iLCtjlooTzuR0lpmB8I6hPX/VupcGQ3Z1U2+wgJJ4fa8+cWkub+lCsbZcYPzBGsZLEL8fQAg+Na5dwEFJxg==", - "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "@csstools/css-parser-algorithms": "^2.1.1", - "@csstools/css-tokenizer": "^2.1.1" - } - }, - "node_modules/@csstools/css-color-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-1.2.1.tgz", - "integrity": "sha512-NcmaoJIEycIH0HnzZRrwRcBljPh1AWcXl4CNL8MAD3+Zy8XyIpdTtTMaY/phnLHHIYkyjaoSTdxAecss6+PCcg==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "dependencies": { - "@csstools/color-helpers": "^2.1.0", - "@csstools/css-calc": "^1.1.1" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "peerDependencies": { - "@csstools/css-parser-algorithms": "^2.1.1", - "@csstools/css-tokenizer": "^2.1.1" - } - }, - "node_modules/@csstools/css-parser-algorithms": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.2.0.tgz", - "integrity": "sha512-9BoQ/jSrPq4vv3b9jjLW+PNNv56KlDH5JMx5yASSNrCtvq70FCNZUjXRvbCeR9hYj9ZyhURtqpU/RFIgg6kiOw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "engines": { - "node": "^14 || ^16 || >=18" - }, - "peerDependencies": { - "@csstools/css-tokenizer": "^2.1.1" - } - }, - "node_modules/@csstools/css-tokenizer": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-2.1.1.tgz", - "integrity": "sha512-GbrTj2Z8MCTUv+52GE0RbFGM527xuXZ0Xa5g0Z+YN573uveS4G0qi6WNOMyz3yrFM/jaILTTwJ0+umx81EzqfA==", - "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - }, - "node_modules/@csstools/media-query-list-parser": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.0.tgz", - "integrity": "sha512-MXkR+TeaS2q9IkpyO6jVCdtA/bfpABJxIrfkLswThFN8EZZgI2RfAHhm6sDNDuYV25d5+b8Lj1fpTccIcSLPsQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "engines": { - "node": "^14 || ^16 || >=18" - }, - "peerDependencies": { - "@csstools/css-parser-algorithms": "^2.1.1", - "@csstools/css-tokenizer": "^2.1.1" - } - }, - "node_modules/@csstools/postcss-cascade-layers": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-cascade-layers/-/postcss-cascade-layers-3.0.1.tgz", - "integrity": "sha512-dD8W98dOYNOH/yX4V4HXOhfCOnvVAg8TtsL+qCGNoKXuq5z2C/d026wGWgySgC8cajXXo/wNezS31Glj5GcqrA==", - "dependencies": { - "@csstools/selector-specificity": "^2.0.2", - "postcss-selector-parser": "^6.0.10" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/@csstools/postcss-color-function": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-2.2.3.tgz", - "integrity": "sha512-b1ptNkr1UWP96EEHqKBWWaV5m/0hgYGctgA/RVZhONeP1L3T/8hwoqDm9bB23yVCfOgE9U93KI9j06+pEkJTvw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "dependencies": { - "@csstools/css-color-parser": "^1.2.0", - "@csstools/css-parser-algorithms": "^2.1.1", - "@csstools/css-tokenizer": "^2.1.1", - "@csstools/postcss-progressive-custom-properties": "^2.3.0" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/@csstools/postcss-color-mix-function": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@csstools/postcss-color-mix-function/-/postcss-color-mix-function-1.0.3.tgz", - "integrity": "sha512-QGXjGugTluqFZWzVf+S3wCiRiI0ukXlYqCi7OnpDotP/zaVTyl/aqZujLFzTOXy24BoWnu89frGMc79ohY5eog==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "dependencies": { - "@csstools/css-color-parser": "^1.2.0", - "@csstools/css-parser-algorithms": "^2.1.1", - "@csstools/css-tokenizer": "^2.1.1", - "@csstools/postcss-progressive-custom-properties": "^2.3.0" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/@csstools/postcss-font-format-keywords": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@csstools/postcss-font-format-keywords/-/postcss-font-format-keywords-2.0.2.tgz", - "integrity": "sha512-iKYZlIs6JsNT7NKyRjyIyezTCHLh4L4BBB3F5Nx7Dc4Z/QmBgX+YJFuUSar8IM6KclGiAUFGomXFdYxAwJydlA==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/@csstools/postcss-gradients-interpolation-method": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@csstools/postcss-gradients-interpolation-method/-/postcss-gradients-interpolation-method-3.0.6.tgz", - "integrity": "sha512-rBOBTat/YMmB0G8VHwKqDEx+RZ4KCU9j42K8LwS0IpZnyThalZZF7BCSsZ6TFlZhcRZKlZy3LLFI2pLqjNVGGA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "dependencies": { - "@csstools/css-color-parser": "^1.2.0", - "@csstools/css-parser-algorithms": "^2.1.1", - "@csstools/css-tokenizer": "^2.1.1", - "@csstools/postcss-progressive-custom-properties": "^2.3.0" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/@csstools/postcss-hwb-function": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@csstools/postcss-hwb-function/-/postcss-hwb-function-2.2.2.tgz", - "integrity": "sha512-W5Y5oaJ382HSlbdGfPf60d7dAK6Hqf10+Be1yZbd/TNNrQ/3dDdV1c07YwOXPQ3PZ6dvFMhxbIbn8EC3ki3nEg==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "dependencies": { - "@csstools/css-color-parser": "^1.2.0", - "@csstools/css-parser-algorithms": "^2.1.1", - "@csstools/css-tokenizer": "^2.1.1" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/@csstools/postcss-ic-unit": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@csstools/postcss-ic-unit/-/postcss-ic-unit-2.0.4.tgz", - "integrity": "sha512-9W2ZbV7whWnr1Gt4qYgxMWzbevZMOvclUczT5vk4yR6vS53W/njiiUhtm/jh/BKYwQ1W3PECZjgAd2dH4ebJig==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "dependencies": { - "@csstools/postcss-progressive-custom-properties": "^2.3.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/@csstools/postcss-is-pseudo-class": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-3.2.1.tgz", - "integrity": "sha512-AtANdV34kJl04Al62is3eQRk/BfOfyAvEmRJvbt+nx5REqImLC+2XhuE6skgkcPli1l8ONS67wS+l1sBzySc3Q==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "dependencies": { - "@csstools/selector-specificity": "^2.0.0", - "postcss-selector-parser": "^6.0.10" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/@csstools/postcss-logical-float-and-clear": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-float-and-clear/-/postcss-logical-float-and-clear-1.0.1.tgz", - "integrity": "sha512-eO9z2sMLddvlfFEW5Fxbjyd03zaO7cJafDurK4rCqyRt9P7aaWwha0LcSzoROlcZrw1NBV2JAp2vMKfPMQO1xw==", - "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/@csstools/postcss-logical-resize": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-resize/-/postcss-logical-resize-1.0.1.tgz", - "integrity": "sha512-x1ge74eCSvpBkDDWppl+7FuD2dL68WP+wwP2qvdUcKY17vJksz+XoE1ZRV38uJgS6FNUwC0AxrPW5gy3MxsDHQ==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/@csstools/postcss-logical-viewport-units": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-viewport-units/-/postcss-logical-viewport-units-1.0.3.tgz", - "integrity": "sha512-6zqcyRg9HSqIHIPMYdt6THWhRmE5/tyHKJQLysn2TeDf/ftq7Em9qwMTx98t2C/7UxIsYS8lOiHHxAVjWn2WUg==", - "dependencies": { - "@csstools/css-tokenizer": "^2.1.1" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/@csstools/postcss-media-minmax": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@csstools/postcss-media-minmax/-/postcss-media-minmax-1.0.3.tgz", - "integrity": "sha512-os7qe2HV/qBILKCGa/dl5AbpO6c+MZyunFBWPWJBrEVhulCYo13FgEWbhyERFM5FeJghiqYgJxM54oiJASpBnw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "dependencies": { - "@csstools/css-calc": "^1.1.1", - "@csstools/css-parser-algorithms": "^2.1.1", - "@csstools/css-tokenizer": "^2.1.1", - "@csstools/media-query-list-parser": "^2.1.0" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/@csstools/postcss-media-queries-aspect-ratio-number-values": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@csstools/postcss-media-queries-aspect-ratio-number-values/-/postcss-media-queries-aspect-ratio-number-values-1.0.3.tgz", - "integrity": "sha512-JHdwBSNZsur/mJXwzuC/gxyekhfSdWJaTiSOhUITk2D8pYRYcjV1MZiCiWupQNfM2Qp2W7w1A/gEU6U/xlpIyA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "dependencies": { - "@csstools/css-parser-algorithms": "^2.1.1", - "@csstools/css-tokenizer": "^2.1.1", - "@csstools/media-query-list-parser": "^2.1.0" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/@csstools/postcss-nested-calc": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@csstools/postcss-nested-calc/-/postcss-nested-calc-2.0.2.tgz", - "integrity": "sha512-jbwrP8rN4e7LNaRcpx3xpMUjhtt34I9OV+zgbcsYAAk6k1+3kODXJBf95/JMYWhu9g1oif7r06QVUgfWsKxCFw==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/@csstools/postcss-normalize-display-values": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-normalize-display-values/-/postcss-normalize-display-values-2.0.1.tgz", - "integrity": "sha512-TQT5g3JQ5gPXC239YuRK8jFceXF9d25ZvBkyjzBGGoW5st5sPXFVQS8OjYb9IJ/K3CdfK4528y483cgS2DJR/w==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/@csstools/postcss-oklab-function": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-2.2.3.tgz", - "integrity": "sha512-AgJ2rWMnLCDcbSMTHSqBYn66DNLBym6JpBpCaqmwZ9huGdljjDRuH3DzOYzkgQ7Pm2K92IYIq54IvFHloUOdvA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "dependencies": { - "@csstools/css-color-parser": "^1.2.0", - "@csstools/css-parser-algorithms": "^2.1.1", - "@csstools/css-tokenizer": "^2.1.1", - "@csstools/postcss-progressive-custom-properties": "^2.3.0" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/@csstools/postcss-progressive-custom-properties": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-2.3.0.tgz", - "integrity": "sha512-Zd8ojyMlsL919TBExQ1I0CTpBDdyCpH/yOdqatZpuC3sd22K4SwC7+Yez3Q/vmXMWSAl+shjNeFZ7JMyxMjK+Q==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/@csstools/postcss-relative-color-syntax": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@csstools/postcss-relative-color-syntax/-/postcss-relative-color-syntax-1.0.2.tgz", - "integrity": "sha512-juCoVInkgH2TZPfOhyx6tIal7jW37L/0Tt+Vcl1LoxqQA9sxcg3JWYZ98pl1BonDnki6s/M7nXzFQHWsWMeHgw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "dependencies": { - "@csstools/css-color-parser": "^1.2.0", - "@csstools/css-parser-algorithms": "^2.1.1", - "@csstools/css-tokenizer": "^2.1.1", - "@csstools/postcss-progressive-custom-properties": "^2.3.0" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/@csstools/postcss-scope-pseudo-class": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@csstools/postcss-scope-pseudo-class/-/postcss-scope-pseudo-class-2.0.2.tgz", - "integrity": "sha512-6Pvo4uexUCXt+Hz5iUtemQAcIuCYnL+ePs1khFR6/xPgC92aQLJ0zGHonWoewiBE+I++4gXK3pr+R1rlOFHe5w==", - "dependencies": { - "postcss-selector-parser": "^6.0.10" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/@csstools/postcss-stepped-value-functions": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-stepped-value-functions/-/postcss-stepped-value-functions-2.1.1.tgz", - "integrity": "sha512-YCvdF0GCZK35nhLgs7ippcxDlRVe5QsSht3+EghqTjnYnyl3BbWIN6fYQ1dKWYTJ+7Bgi41TgqQFfJDcp9Xy/w==", - "dependencies": { - "@csstools/css-calc": "^1.1.1", - "@csstools/css-parser-algorithms": "^2.1.1", - "@csstools/css-tokenizer": "^2.1.1" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/@csstools/postcss-text-decoration-shorthand": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-2.2.4.tgz", - "integrity": "sha512-zPN56sQkS/7YTCVZhOBVCWf7AiNge8fXDl7JVaHLz2RyT4pnyK2gFjckWRLpO0A2xkm1lCgZ0bepYZTwAVd/5A==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "dependencies": { - "@csstools/color-helpers": "^2.1.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/@csstools/postcss-trigonometric-functions": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-trigonometric-functions/-/postcss-trigonometric-functions-2.1.1.tgz", - "integrity": "sha512-XcXmHEFfHXhvYz40FtDlA4Fp4NQln2bWTsCwthd2c+MCnYArUYU3YaMqzR5CrKP3pMoGYTBnp5fMqf1HxItNyw==", - "dependencies": { - "@csstools/css-calc": "^1.1.1", - "@csstools/css-parser-algorithms": "^2.1.1", - "@csstools/css-tokenizer": "^2.1.1" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/@csstools/postcss-unset-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-unset-value/-/postcss-unset-value-2.0.1.tgz", - "integrity": "sha512-oJ9Xl29/yU8U7/pnMJRqAZd4YXNCfGEdcP4ywREuqm/xMqcgDNDppYRoCGDt40aaZQIEKBS79LytUDN/DHf0Ew==", - "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/@csstools/selector-specificity": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.2.0.tgz", - "integrity": "sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw==", - "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss-selector-parser": "^6.0.10" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "peer": true, - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", - "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", - "peer": true, - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz", - "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==", - "peer": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.5.2", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/js": { - "version": "8.43.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.43.0.tgz", - "integrity": "sha512-s2UHCoiXfxMvmfzqoN+vrQ84ahUSYde9qNO1MdxmoEhyHWsfmwOpFlwYV+ePJEVc7gFnATGUi376WowX1N7tFg==", - "peer": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", - "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", - "peer": true, - "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "peer": true, - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "peer": true - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", - "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - } - }, - "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, - "node_modules/@next/env": { - "version": "13.1.4", - "resolved": "https://registry.npmjs.org/@next/env/-/env-13.1.4.tgz", - "integrity": "sha512-x7ydhMpi9/xX7yVK+Fw33OuwwQWVZUFRxenK3z89fmPzQZyUk35Ynb+b7JkrhfRhDIFFvvqpzVSXeseSlBAw7A==" - }, - "node_modules/@next/eslint-plugin-next": { - "version": "13.1.4", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-13.1.4.tgz", - "integrity": "sha512-a/T30+7Q1scom5t3L+wEBkYzCa+bhT/3DTxzxlNy4Xckw2InzcckQGeIi/larDgh5r2fSSJswhYAZEcKtuJiig==", - "dependencies": { - "glob": "7.1.7" - } - }, - "node_modules/@next/font": { - "version": "13.1.4", - "resolved": "https://registry.npmjs.org/@next/font/-/font-13.1.4.tgz", - "integrity": "sha512-NfqQPAIFJhssdaZEsP0MADZKN+tc040jOkNKVlDZHtVjJWBJSgbe8UHg3w0S6YuQr7PHc0ACbFeVCBQeG4MEvg==" - }, - "node_modules/@next/swc-android-arm-eabi": { - "version": "13.1.4", - "resolved": "https://registry.npmjs.org/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-13.1.4.tgz", - "integrity": "sha512-5PAchzFst3In6Ml+9APvBj89H29lcPXcUqEYBVv09fWK/V4IuViKc2qOqM9pyPyw7KsqaZPmuqaG595E6jdZLA==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-android-arm64": { - "version": "13.1.4", - "resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-13.1.4.tgz", - "integrity": "sha512-LCLjjRhsQ5fR9ExzR2fqxuyJe/D4Ct/YkdonVfJfqOfkEpFwUTQDOVo5GrQec4LZDk3zY+o6vZYjXbB0nD9VLA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-darwin-arm64": { - "version": "13.1.4", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.1.4.tgz", - "integrity": "sha512-LSc/tF1FQ1y1SwKiCdGg8IIl7+Csk6nuLcLIyQXs24UNYjXg5+7vUQXqE8y66v/Dq8qFDC9rM61QhpM9ZDftbg==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-darwin-x64": { - "version": "13.1.4", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.1.4.tgz", - "integrity": "sha512-WoApDo8xfafrNc9+Mz5MwGFKUwbDHsGqLleTGZ8upegwVqDyHsYzqJQudf+loqhV58oGTOqP1eWaHn2J7dijXA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-freebsd-x64": { - "version": "13.1.4", - "resolved": "https://registry.npmjs.org/@next/swc-freebsd-x64/-/swc-freebsd-x64-13.1.4.tgz", - "integrity": "sha512-fqNyeT8G4guN8AHPIoBRhGY2GJg89FyWpuwX4o0Y3vUy/84IGZpNst3paCzaYkQSqQE/AuCpkB7hKxkN7ittXw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm-gnueabihf": { - "version": "13.1.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-13.1.4.tgz", - "integrity": "sha512-MEfm8OC1YR9/tYHUzlQsxcSmiuf8XdO7bqh5VtG4pilScjc5I5t+tQgIDgoDGePfh5W99W23hb3s6oCFrt99rw==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-gnu": { - "version": "13.1.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.1.4.tgz", - "integrity": "sha512-2wgth/KsuODzW/E7jsRoWdhKmE5oZzXcBPvf9RW+ZpBNvYQkEDlzfLA7n8DtxTU8I4oMas0mdEPdCWXrSNnVZw==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-musl": { - "version": "13.1.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.1.4.tgz", - "integrity": "sha512-GdWhCRljsT7rNEElEsdu4RRppd+XaQOX1IJslsh/+HU6LsJGUE8tXpa68yJjCsHZHifkbdZNeCr5SYdsN6CbAA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-gnu": { - "version": "13.1.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.1.4.tgz", - "integrity": "sha512-Rsk/ojwYqMskN2eo5hUSVe7UuMV/aSjmrmJ0BCFGFPfBY9sPgmYj/oXlDDN0y5lJD9acPuiBjknLWgnOnx5JIA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-musl": { - "version": "13.1.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.1.4.tgz", - "integrity": "sha512-gKSVPozedA2gpA+vggYnAqpDuzWFed2oxFeXxHw0aW2ALdAZswAinn1ZwXEQ5fHnVguxjZhH0+2nBxpMdF8p5Q==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-arm64-msvc": { - "version": "13.1.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.1.4.tgz", - "integrity": "sha512-+kAXIIVb7Q4LCKmi7dn9qVlG1XUf3Chgj5Rwl0rAP4WBV2TnJIgsOEC24G1Mm3jjif+qXm7SJS9YZ9Yg3Y8sSQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-ia32-msvc": { - "version": "13.1.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.1.4.tgz", - "integrity": "sha512-EsfzAFBVaw1zg1FzlLMgRaTX/DKY+EnAvJ6mCIJMGeSOPIj4Oy6xF2yEQ3VaRkwFpAafHJH6JNB/CGrdKFCMXw==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-x64-msvc": { - "version": "13.1.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.1.4.tgz", - "integrity": "sha512-bygNjmnq+F9NqJXh7OfhJgqu6LGU29GNKQYVyZkxY/h5K0WWUvAE/VL+TdyMwbvQr9KByx5XLwORwetLxXCo4g==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "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==", - "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==", - "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==", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@pkgr/utils": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.4.1.tgz", - "integrity": "sha512-JOqwkgFEyi+OROIyq7l4Jy28h/WwhDnG/cPkXG2Z1iFbubB6jsHW1NDvmyOzTBxHr3yg68YGirmh1JUgMqa+9w==", - "dependencies": { - "cross-spawn": "^7.0.3", - "fast-glob": "^3.2.12", - "is-glob": "^4.0.3", - "open": "^9.1.0", - "picocolors": "^1.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, - "node_modules/@popperjs/core": { - "version": "2.11.8", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", - "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/popperjs" - } - }, - "node_modules/@rushstack/eslint-patch": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.3.2.tgz", - "integrity": "sha512-V+MvGwaHH03hYhY+k6Ef/xKd6RYlc4q8WBx+2ANmipHJcKuktNcI/NgEsJgdSUF6Lw32njT6OnrRsKYCdgHjYw==" - }, - "node_modules/@swc/helpers": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.14.tgz", - "integrity": "sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==", - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" - }, - "node_modules/@types/node": { - "version": "18.11.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz", - "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==" - }, - "node_modules/@types/prop-types": { - "version": "15.7.5", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", - "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==" - }, - "node_modules/@types/react": { - "version": "18.0.27", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.27.tgz", - "integrity": "sha512-3vtRKHgVxu3Jp9t718R9BuzoD4NcQ8YJ5XRzsSKxNDiDonD2MXIT1TmSkenxuCycZJoQT5d2vE8LwWJxBC1gmA==", - "dependencies": { - "@types/prop-types": "*", - "@types/scheduler": "*", - "csstype": "^3.0.2" - } - }, - "node_modules/@types/react-datepicker": { - "version": "4.11.2", - "resolved": "https://registry.npmjs.org/@types/react-datepicker/-/react-datepicker-4.11.2.tgz", - "integrity": "sha512-ELYyX3lb3K1WltqdlF1hbnaDGgzlF6PIR5T4W38cSEcfrQDIrPE+Ioq5pwRe/KEJ+ihHMjvTVZQkwJx0pWMNHQ==", - "dev": true, - "dependencies": { - "@popperjs/core": "^2.9.2", - "@types/react": "*", - "date-fns": "^2.0.1", - "react-popper": "^2.2.5" - } - }, - "node_modules/@types/react-dom": { - "version": "18.0.10", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.10.tgz", - "integrity": "sha512-E42GW/JA4Qv15wQdqJq8DL4JhNpB3prJgjgapN3qJT9K2zO5IIAQh4VXvCEDupoqAwnz0cY4RlXeC/ajX5SFHg==", - "dependencies": { - "@types/react": "*" - } - }, - "node_modules/@types/scheduler": { - "version": "0.16.3", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", - "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==" - }, - "node_modules/@typescript-eslint/parser": { - "version": "5.59.11", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.11.tgz", - "integrity": "sha512-s9ZF3M+Nym6CAZEkJJeO2TFHHDsKAM3ecNkLuH4i4s8/RCPnF5JRip2GyviYkeEAcwGMJxkqG9h2dAsnA1nZpA==", - "dependencies": { - "@typescript-eslint/scope-manager": "5.59.11", - "@typescript-eslint/types": "5.59.11", - "@typescript-eslint/typescript-estree": "5.59.11", - "debug": "^4.3.4" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "5.59.11", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.11.tgz", - "integrity": "sha512-dHFOsxoLFtrIcSj5h0QoBT/89hxQONwmn3FOQ0GOQcLOOXm+MIrS8zEAhs4tWl5MraxCY3ZJpaXQQdFMc2Tu+Q==", - "dependencies": { - "@typescript-eslint/types": "5.59.11", - "@typescript-eslint/visitor-keys": "5.59.11" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "5.59.11", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.11.tgz", - "integrity": "sha512-epoN6R6tkvBYSc+cllrz+c2sOFWkbisJZWkOE+y3xHtvYaOE6Wk6B8e114McRJwFRjGvYdJwLXQH5c9osME/AA==", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.59.11", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.11.tgz", - "integrity": "sha512-YupOpot5hJO0maupJXixi6l5ETdrITxeo5eBOeuV7RSKgYdU3G5cxO49/9WRnJq9EMrB7AuTSLH/bqOsXi7wPA==", - "dependencies": { - "@typescript-eslint/types": "5.59.11", - "@typescript-eslint/visitor-keys": "5.59.11", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.59.11", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.11.tgz", - "integrity": "sha512-KGYniTGG3AMTuKF9QBD7EIrvufkB6O6uX3knP73xbKLMpH+QRPcgnCxjWXSHjMRuOxFLovljqQgQpR0c7GvjoA==", - "dependencies": { - "@typescript-eslint/types": "5.59.11", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/acorn": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.9.0.tgz", - "integrity": "sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==", - "peer": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "peer": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "peer": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "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==", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "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==", - "peer": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "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/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "peer": true - }, - "node_modules/aria-query": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.2.1.tgz", - "integrity": "sha512-7uFg4b+lETFgdaJyETnILsXgnnzVnkHcgRbwbPwevm5x/LmUlt3MjczMRe1zg824iBgXZNRPTBftNYyRSKLp2g==", - "dependencies": { - "dequal": "^2.0.3" - } - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", - "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-includes": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", - "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "engines": { - "node": ">=8" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", - "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", - "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.tosorted": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.1.tgz", - "integrity": "sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.1.3" - } - }, - "node_modules/ast-types-flow": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", - "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==" - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "node_modules/autoprefixer": { - "version": "10.4.14", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz", - "integrity": "sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/autoprefixer" - } - ], - "dependencies": { - "browserslist": "^4.21.5", - "caniuse-lite": "^1.0.30001464", - "fraction.js": "^4.2.0", - "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/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/axe-core": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.2.tgz", - "integrity": "sha512-zIURGIS1E1Q4pcrMjp+nnEh+16G56eG/MUllJH8yEvw7asDo7Ac9uhC9KIH5jzpITueEZolfYglnCGIuSBz39g==", - "engines": { - "node": ">=4" - } - }, - "node_modules/axios": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", - "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", - "dependencies": { - "follow-redirects": "^1.15.0", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/axobject-query": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", - "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==", - "dependencies": { - "dequal": "^2.0.3" - } - }, - "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==" - }, - "node_modules/big-integer": { - "version": "1.6.51", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", - "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/bplist-parser": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", - "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", - "dependencies": { - "big-integer": "^1.6.44" - }, - "engines": { - "node": ">= 5.10.0" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.21.9", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.9.tgz", - "integrity": "sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==", - "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.30001503", - "electron-to-chromium": "^1.4.431", - "node-releases": "^2.0.12", - "update-browserslist-db": "^1.0.11" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/bundle-name": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz", - "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==", - "dependencies": { - "run-applescript": "^5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "peer": true, - "engines": { - "node": ">=6" - } - }, - "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.30001503", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001503.tgz", - "integrity": "sha512-Sf9NiF+wZxPfzv8Z3iS0rXM1Do+iOy2Lxvib38glFX+08TCYYYGR5fRJXk4d77C4AYwhUjgYgMsMudbh2TqCKw==", - "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/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "peer": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "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" - }, - "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/classnames": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", - "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" - }, - "node_modules/client-only": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", - "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" - }, - "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==", - "peer": 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==", - "peer": true - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "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/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "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==", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/css-blank-pseudo": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-5.0.2.tgz", - "integrity": "sha512-aCU4AZ7uEcVSUzagTlA9pHciz7aWPKA/YzrEkpdSopJ2pvhIxiQ5sYeMz1/KByxlIo4XBdvMNJAVKMg/GRnhfw==", - "dependencies": { - "postcss-selector-parser": "^6.0.10" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/css-has-pseudo": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-5.0.2.tgz", - "integrity": "sha512-q+U+4QdwwB7T9VEW/LyO6CFrLAeLqOykC5mDqJXc7aKZAhDbq7BvGT13VGJe+IwBfdN2o3Xdw2kJ5IxwV1Sc9Q==", - "dependencies": { - "@csstools/selector-specificity": "^2.0.1", - "postcss-selector-parser": "^6.0.10", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/css-prefers-color-scheme": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-8.0.2.tgz", - "integrity": "sha512-OvFghizHJ45x7nsJJUSYLyQNTzsCU8yWjxAc/nhPQg1pbs18LMoET8N3kOweFDPy0JV0OSXN2iqRFhPBHYOeMA==", - "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/cssdb": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-7.6.0.tgz", - "integrity": "sha512-Nna7rph8V0jC6+JBY4Vk4ndErUmfJfV6NJCaZdurL0omggabiy+QB2HCQtu5c/ACLZ0I7REv7A4QyPIoYzZx0w==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - } - ] - }, - "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==", - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/csstype": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", - "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" - }, - "node_modules/damerau-levenshtein": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", - "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==" - }, - "node_modules/data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", - "engines": { - "node": ">= 12" - } - }, - "node_modules/date-fns": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", - "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", - "dependencies": { - "@babel/runtime": "^7.21.0" - }, - "engines": { - "node": ">=0.11" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/date-fns" - } - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "peer": true - }, - "node_modules/deepmerge": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz", - "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/default-browser": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz", - "integrity": "sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==", - "dependencies": { - "bundle-name": "^3.0.0", - "default-browser-id": "^3.0.0", - "execa": "^7.1.1", - "titleize": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-browser-id": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz", - "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==", - "dependencies": { - "bplist-parser": "^0.2.0", - "untildify": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/define-lazy-prop": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", - "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", - "dependencies": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "engines": { - "node": ">=6" - } - }, - "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/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "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/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "peer": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.4.433", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.433.tgz", - "integrity": "sha512-MGO1k0w1RgrfdbLVwmXcDhHHuxCn2qRgR7dYsJvWFKDttvYPx6FNzCGG0c/fBBvzK2LDh3UV7Tt9awnHnvAAUQ==" - }, - "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==" - }, - "node_modules/enhanced-resolve": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", - "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/es-abstract": { - "version": "1.21.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", - "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==", - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-set-tostringtag": "^2.0.1", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.2.0", - "get-symbol-description": "^1.0.0", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", - "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.10", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.3", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.7", - "string.prototype.trimend": "^1.0.6", - "string.prototype.trimstart": "^1.0.6", - "typed-array-length": "^1.0.4", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.9" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", - "dependencies": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", - "dependencies": { - "has": "^1.0.3" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "8.43.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.43.0.tgz", - "integrity": "sha512-aaCpf2JqqKesMFGgmRPessmVKjcGXqdlAYLLC3THM8t5nBRZRQ+st5WM/hoJXkdioEXLLbXgclUpM0TXo5HX5Q==", - "peer": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.0.3", - "@eslint/js": "8.43.0", - "@humanwhocodes/config-array": "^0.11.10", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.0", - "eslint-visitor-keys": "^3.4.1", - "espree": "^9.5.2", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-next": { - "version": "13.1.4", - "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-13.1.4.tgz", - "integrity": "sha512-r7n9V4/kkiDDVFfBwI3tviGUV/jUzGI0lY3JefxceYaU18gdk2kMgNPyhHobowu1+yHZpZi8iEzRtzeTrtGRLg==", - "dependencies": { - "@next/eslint-plugin-next": "13.1.4", - "@rushstack/eslint-patch": "^1.1.3", - "@typescript-eslint/parser": "^5.42.0", - "eslint-import-resolver-node": "^0.3.6", - "eslint-import-resolver-typescript": "^3.5.2", - "eslint-plugin-import": "^2.26.0", - "eslint-plugin-jsx-a11y": "^6.5.1", - "eslint-plugin-react": "^7.31.7", - "eslint-plugin-react-hooks": "^4.5.0" - }, - "peerDependencies": { - "eslint": "^7.23.0 || ^8.0.0", - "typescript": ">=3.3.1" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz", - "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==", - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.11.0", - "resolve": "^1.22.1" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-import-resolver-typescript": { - "version": "3.5.5", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.5.5.tgz", - "integrity": "sha512-TdJqPHs2lW5J9Zpe17DZNQuDnox4xo2o+0tE7Pggain9Rbc19ik8kFtXdxZ250FVx2kF4vlt2RSf4qlUpG7bhw==", - "dependencies": { - "debug": "^4.3.4", - "enhanced-resolve": "^5.12.0", - "eslint-module-utils": "^2.7.4", - "get-tsconfig": "^4.5.0", - "globby": "^13.1.3", - "is-core-module": "^2.11.0", - "is-glob": "^4.0.3", - "synckit": "^0.8.5" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" - }, - "peerDependencies": { - "eslint": "*", - "eslint-plugin-import": "*" - } - }, - "node_modules/eslint-import-resolver-typescript/node_modules/globby": { - "version": "13.1.4", - "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.4.tgz", - "integrity": "sha512-iui/IiiW+QrJ1X1hKH5qwlMQyv34wJAYwH1vrf8b9kBA4sNiif3gKsMHa+BrdnOpEudWjpotfa7LrTzB1ERS/g==", - "dependencies": { - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.11", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint-import-resolver-typescript/node_modules/slash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint-module-utils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", - "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", - "dependencies": { - "debug": "^3.2.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import": { - "version": "2.27.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz", - "integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==", - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "array.prototype.flatmap": "^1.3.1", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.7", - "eslint-module-utils": "^2.7.4", - "has": "^1.0.3", - "is-core-module": "^2.11.0", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.values": "^1.1.6", - "resolve": "^1.22.1", - "semver": "^6.3.0", - "tsconfig-paths": "^3.14.1" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-plugin-jsx-a11y": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.7.1.tgz", - "integrity": "sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA==", - "dependencies": { - "@babel/runtime": "^7.20.7", - "aria-query": "^5.1.3", - "array-includes": "^3.1.6", - "array.prototype.flatmap": "^1.3.1", - "ast-types-flow": "^0.0.7", - "axe-core": "^4.6.2", - "axobject-query": "^3.1.1", - "damerau-levenshtein": "^1.0.8", - "emoji-regex": "^9.2.2", - "has": "^1.0.3", - "jsx-ast-utils": "^3.3.3", - "language-tags": "=1.0.5", - "minimatch": "^3.1.2", - "object.entries": "^1.1.6", - "object.fromentries": "^2.0.6", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=4.0" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" - } - }, - "node_modules/eslint-plugin-jsx-a11y/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-plugin-react": { - "version": "7.32.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz", - "integrity": "sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg==", - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flatmap": "^1.3.1", - "array.prototype.tosorted": "^1.1.1", - "doctrine": "^2.1.0", - "estraverse": "^5.3.0", - "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "minimatch": "^3.1.2", - "object.entries": "^1.1.6", - "object.fromentries": "^2.0.6", - "object.hasown": "^1.1.2", - "object.values": "^1.1.6", - "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.4", - "semver": "^6.3.0", - "string.prototype.matchall": "^4.0.8" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" - } - }, - "node_modules/eslint-plugin-react-hooks": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", - "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" - } - }, - "node_modules/eslint-plugin-react/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.4", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", - "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==", - "dependencies": { - "is-core-module": "^2.9.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/eslint-plugin-react/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-scope": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", - "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", - "peer": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", - "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/espree": { - "version": "9.5.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz", - "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==", - "peer": true, - "dependencies": { - "acorn": "^8.8.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "peer": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "peer": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/execa": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-7.1.1.tgz", - "integrity": "sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q==", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.1", - "human-signals": "^4.3.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^3.0.7", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": "^14.18.0 || ^16.14.0 || >=18.0.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "peer": true - }, - "node_modules/fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", - "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==", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "peer": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "peer": true - }, - "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fetch-blob": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", - "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "paypal", - "url": "https://paypal.me/jimmywarting" - } - ], - "dependencies": { - "node-domexception": "^1.0.0", - "web-streams-polyfill": "^3.0.3" - }, - "engines": { - "node": "^12.20 || >= 14.13" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "peer": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "peer": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "peer": true, - "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", - "peer": true - }, - "node_modules/follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dependencies": { - "is-callable": "^1.1.3" - } - }, - "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/formdata-polyfill": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", - "dependencies": { - "fetch-blob": "^3.1.2" - }, - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/formik": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/formik/-/formik-2.4.2.tgz", - "integrity": "sha512-C6nx0hifW2uENP3M6HpPmnAE6HFWCcd8/sqBZEOHZY6lpHJ5qehsfAy43ktpFLEmkBmhiZDei726utcUB9leqg==", - "funding": [ - { - "type": "individual", - "url": "https://opencollective.com/formik" - } - ], - "dependencies": { - "deepmerge": "^2.1.1", - "hoist-non-react-statics": "^3.3.0", - "lodash": "^4.17.21", - "lodash-es": "^4.17.21", - "react-fast-compare": "^2.0.1", - "tiny-warning": "^1.0.2", - "tslib": "^2.0.0" - }, - "peerDependencies": { - "react": ">=16.8.0" - } - }, - "node_modules/fraction.js": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", - "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", - "engines": { - "node": "*" - }, - "funding": { - "type": "patreon", - "url": "https://www.patreon.com/infusion" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "node_modules/function.prototype.name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", - "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-tsconfig": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.6.0.tgz", - "integrity": "sha512-lgbo68hHTQnFddybKbbs/RDRJnJT5YyGy2kQzVwbq+g67X73i+5MVTval34QxGkOe9X5Ujf1UYpCaphLyltjEg==", - "dependencies": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, - "node_modules/glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "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==", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", - "peer": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", - "dependencies": { - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "peer": true - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", - "dependencies": { - "get-intrinsic": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hoist-non-react-statics": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", - "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", - "dependencies": { - "react-is": "^16.7.0" - } - }, - "node_modules/human-signals": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", - "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", - "engines": { - "node": ">=14.18.0" - } - }, - "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "peer": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "peer": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", - "dependencies": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz", - "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==", - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-docker": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", - "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "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==", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-inside-container": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", - "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", - "dependencies": { - "is-docker": "^3.0.0" - }, - "bin": { - "is-inside-container": "cli.js" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", - "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-wsl/node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" - }, - "node_modules/isomorphic-unfetch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/isomorphic-unfetch/-/isomorphic-unfetch-4.0.2.tgz", - "integrity": "sha512-1Yd+CF/7al18/N2BDbsLBcp6RO3tucSW+jcLq24dqdX5MNbCNTw1z4BsGsp4zNmjr/Izm2cs/cEqZPp4kvWSCA==", - "dependencies": { - "node-fetch": "^3.2.0", - "unfetch": "^5.0.0" - } - }, - "node_modules/jiti": { - "version": "1.18.2", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.18.2.tgz", - "integrity": "sha512-QAdOptna2NYiSSpv0O/BwoHBSmz4YhpzJHyi+fnMRTXFjp7B8i/YG5Z8IfusxB1ufjcD2Sre1F3R+nX3fvy7gg==", - "dev": true, - "bin": { - "jiti": "bin/jiti.js" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "peer": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "peer": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "peer": true - }, - "node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/jsx-ast-utils": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz", - "integrity": "sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==", - "dependencies": { - "array-includes": "^3.1.5", - "object.assign": "^4.1.3" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/language-subtag-registry": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", - "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==" - }, - "node_modules/language-tags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", - "integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==", - "dependencies": { - "language-subtag-registry": "~0.3.2" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "peer": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.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/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "peer": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "node_modules/lodash-es": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", - "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "peer": true - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "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.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", - "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/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "peer": true - }, - "node_modules/next": { - "version": "13.1.4", - "resolved": "https://registry.npmjs.org/next/-/next-13.1.4.tgz", - "integrity": "sha512-g0oBUU+tcOPKbXTVdsDO2adc6wd/ggqauHHysPQJxuIKqZ+fwICGJht0C5D5V0A/77eQDF5EFwNdAHkFvBDsog==", - "dependencies": { - "@next/env": "13.1.4", - "@swc/helpers": "0.4.14", - "caniuse-lite": "^1.0.30001406", - "postcss": "8.4.14", - "styled-jsx": "5.1.1" - }, - "bin": { - "next": "dist/bin/next" - }, - "engines": { - "node": ">=14.6.0" - }, - "optionalDependencies": { - "@next/swc-android-arm-eabi": "13.1.4", - "@next/swc-android-arm64": "13.1.4", - "@next/swc-darwin-arm64": "13.1.4", - "@next/swc-darwin-x64": "13.1.4", - "@next/swc-freebsd-x64": "13.1.4", - "@next/swc-linux-arm-gnueabihf": "13.1.4", - "@next/swc-linux-arm64-gnu": "13.1.4", - "@next/swc-linux-arm64-musl": "13.1.4", - "@next/swc-linux-x64-gnu": "13.1.4", - "@next/swc-linux-x64-musl": "13.1.4", - "@next/swc-win32-arm64-msvc": "13.1.4", - "@next/swc-win32-ia32-msvc": "13.1.4", - "@next/swc-win32-x64-msvc": "13.1.4" - }, - "peerDependencies": { - "fibers": ">= 3.1.0", - "node-sass": "^6.0.0 || ^7.0.0", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "sass": "^1.3.0" - }, - "peerDependenciesMeta": { - "fibers": { - "optional": true - }, - "node-sass": { - "optional": true - }, - "sass": { - "optional": true - } - } - }, - "node_modules/next/node_modules/postcss": { - "version": "8.4.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", - "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - } - ], - "dependencies": { - "nanoid": "^3.3.4", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/node-domexception": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "github", - "url": "https://paypal.me/jimmywarting" - } - ], - "engines": { - "node": ">=10.5.0" - } - }, - "node_modules/node-fetch": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.1.tgz", - "integrity": "sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==", - "dependencies": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-fetch" - } - }, - "node_modules/node-releases": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.12.tgz", - "integrity": "sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==" - }, - "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==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm-run-path": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", - "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", - "dependencies": { - "path-key": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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==", - "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/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.entries": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.6.tgz", - "integrity": "sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.fromentries": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz", - "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.hasown": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.2.tgz", - "integrity": "sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==", - "dependencies": { - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.values": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", - "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dependencies": { - "mimic-fn": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/open": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/open/-/open-9.1.0.tgz", - "integrity": "sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==", - "dependencies": { - "default-browser": "^4.0.0", - "define-lazy-prop": "^3.0.0", - "is-inside-container": "^1.0.0", - "is-wsl": "^2.2.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "peer": true, - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "peer": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "peer": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "peer": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "engines": { - "node": ">=0.10.0" - } - }, - "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==", - "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==" - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "engines": { - "node": ">=8" - } - }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "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.5", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", - "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/postcss": { - "version": "8.4.24", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.24.tgz", - "integrity": "sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg==", - "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.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-attribute-case-insensitive": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-6.0.2.tgz", - "integrity": "sha512-IRuCwwAAQbgaLhxQdQcIIK0dCVXg3XDUnzgKD8iwdiYdwU4rMWRWyl/W9/0nA4ihVpq5pyALiHB2veBJ0292pw==", - "dependencies": { - "postcss-selector-parser": "^6.0.10" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/postcss-clamp": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/postcss-clamp/-/postcss-clamp-4.1.0.tgz", - "integrity": "sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": ">=7.6.0" - }, - "peerDependencies": { - "postcss": "^8.4.6" - } - }, - "node_modules/postcss-color-functional-notation": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-5.1.0.tgz", - "integrity": "sha512-w2R4py6zrVE1U7FwNaAc76tNQlG9GLkrBbcFw+VhUjyDDiV28vfZG+l4LyPmpoQpeSJVtu8VgNjE8Jv5SpC7dQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "dependencies": { - "@csstools/postcss-progressive-custom-properties": "^2.3.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/postcss-color-hex-alpha": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-9.0.2.tgz", - "integrity": "sha512-SfPjgr//VQ/DOCf80STIAsdAs7sbIbxATvVmd+Ec7JvR8onz9pjawhq3BJM3Pie40EE3TyB0P6hft16D33Nlyg==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/postcss-color-rebeccapurple": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-8.0.2.tgz", - "integrity": "sha512-xWf/JmAxVoB5bltHpXk+uGRoGFwu4WDAR7210el+iyvTdqiKpDhtcT8N3edXMoVJY0WHFMrKMUieql/wRNiXkw==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/postcss-custom-media": { - "version": "9.1.4", - "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-9.1.4.tgz", - "integrity": "sha512-4A7WEG3iIyKwfpxL5bkuSlHoHHGRTHl0212Z3uvpwJPyVfZJlkZAQNNgVC+oogrJgksDnfKyuuMbG6HafZPW8Q==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "dependencies": { - "@csstools/cascade-layer-name-parser": "^1.0.2", - "@csstools/css-parser-algorithms": "^2.1.1", - "@csstools/css-tokenizer": "^2.1.1", - "@csstools/media-query-list-parser": "^2.1.0" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/postcss-custom-properties": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-13.2.0.tgz", - "integrity": "sha512-UYiPqbqmVayyv56y0mtGhvUKZClflwE9cTTmPaqEX8fOVjVwsotqKGYtJXSLxrJLwf9tt7ka+Luyh1ZAOhGHWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "dependencies": { - "@csstools/cascade-layer-name-parser": "^1.0.2", - "@csstools/css-parser-algorithms": "^2.1.1", - "@csstools/css-tokenizer": "^2.1.1", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/postcss-custom-selectors": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-7.1.3.tgz", - "integrity": "sha512-GTVscax6O/8s7agFF0HsOoIyjrnAbLjgCUle8tn+0oDGJuVx7p56U7ClSRoC49poxFuMfu2B4Q8GnxSCOeuFKw==", - "dependencies": { - "@csstools/cascade-layer-name-parser": "^1.0.2", - "@csstools/css-parser-algorithms": "^2.1.1", - "@csstools/css-tokenizer": "^2.1.1", - "postcss-selector-parser": "^6.0.4" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/postcss-dir-pseudo-class": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-7.0.2.tgz", - "integrity": "sha512-cMnslilYxBf9k3qejnovrUONZx1rXeUZJw06fgIUBzABJe3D2LiLL5WAER7Imt3nrkaIgG05XZBztueLEf5P8w==", - "dependencies": { - "postcss-selector-parser": "^6.0.10" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/postcss-double-position-gradients": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-4.0.4.tgz", - "integrity": "sha512-nUAbUXURemLXIrl4Xoia2tiu5z/n8sY+BVDZApoeT9BlpByyrp02P/lFCRrRvZ/zrGRE+MOGLhk8o7VcMCtPtQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "dependencies": { - "@csstools/postcss-progressive-custom-properties": "^2.3.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/postcss-focus-visible": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-8.0.2.tgz", - "integrity": "sha512-f/Vd+EC/GaKElknU59esVcRYr/Y3t1ZAQyL4u2xSOgkDy4bMCmG7VP5cGvj3+BTLNE9ETfEuz2nnt4qkZwTTeA==", - "dependencies": { - "postcss-selector-parser": "^6.0.10" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/postcss-focus-within": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-7.0.2.tgz", - "integrity": "sha512-AHAJ89UQBcqBvFgQJE9XasGuwMNkKsGj4D/f9Uk60jFmEBHpAL14DrnSk3Rj+SwZTr/WUG+mh+Rvf8fid/346w==", - "dependencies": { - "postcss-selector-parser": "^6.0.10" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/postcss-font-variant": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz", - "integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==", - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-gap-properties": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-4.0.1.tgz", - "integrity": "sha512-V5OuQGw4lBumPlwHWk/PRfMKjaq/LTGR4WDTemIMCaMevArVfCCA9wBJiL1VjDAd+rzuCIlkRoRvDsSiAaZ4Fg==", - "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/postcss-image-set-function": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-5.0.2.tgz", - "integrity": "sha512-Sszjwo0ubETX0Fi5MvpYzsONwrsjeabjMoc5YqHvURFItXgIu3HdCjcVuVKGMPGzKRhgaknmdM5uVWInWPJmeg==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "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-initial": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-4.0.1.tgz", - "integrity": "sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==", - "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-lab-function": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-5.2.3.tgz", - "integrity": "sha512-fi32AYKzji5/rvgxo5zXHFvAYBw0u0OzELbeCNjEZVLUir18Oj+9RmNphtM8QdLUaUnrfx8zy8vVYLmFLkdmrQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "dependencies": { - "@csstools/css-color-parser": "^1.2.0", - "@csstools/css-parser-algorithms": "^2.1.1", - "@csstools/css-tokenizer": "^2.1.1", - "@csstools/postcss-progressive-custom-properties": "^2.3.0" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/postcss-logical": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-6.2.0.tgz", - "integrity": "sha512-aqlfKGaY0nnbgI9jwUikp4gJKBqcH5noU/EdnIVceghaaDPYhZuyJVxlvWNy55tlTG5tunRKCTAX9yljLiFgmw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/postcss-nested": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz", - "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.11" - }, - "engines": { - "node": ">=12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.2.14" - } - }, - "node_modules/postcss-nesting": { - "version": "11.3.0", - "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-11.3.0.tgz", - "integrity": "sha512-JlS10AQm/RzyrUGgl5irVkAlZYTJ99mNueUl+Qab+TcHhVedLiylWVkKBhRale+rS9yWIJK48JVzQlq3LcSdeA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "dependencies": { - "@csstools/selector-specificity": "^2.0.0", - "postcss-selector-parser": "^6.0.10" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/postcss-opacity-percentage": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-opacity-percentage/-/postcss-opacity-percentage-2.0.0.tgz", - "integrity": "sha512-lyDrCOtntq5Y1JZpBFzIWm2wG9kbEdujpNt4NLannF+J9c8CgFIzPa80YQfdza+Y+yFfzbYj/rfoOsYsooUWTQ==", - "funding": [ - { - "type": "kofi", - "url": "https://ko-fi.com/mrcgrtz" - }, - { - "type": "liberapay", - "url": "https://liberapay.com/mrcgrtz" - } - ], - "engines": { - "node": "^14 || ^16 || >=18" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/postcss-overflow-shorthand": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-4.0.1.tgz", - "integrity": "sha512-HQZ0qi/9iSYHW4w3ogNqVNr2J49DHJAl7r8O2p0Meip38jsdnRPgiDW7r/LlLrrMBMe3KHkvNtAV2UmRVxzLIg==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/postcss-page-break": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-3.0.4.tgz", - "integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==", - "peerDependencies": { - "postcss": "^8" - } - }, - "node_modules/postcss-place": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-8.0.1.tgz", - "integrity": "sha512-Ow2LedN8sL4pq8ubukO77phSVt4QyCm35ZGCYXKvRFayAwcpgB0sjNJglDoTuRdUL32q/ZC1VkPBo0AOEr4Uiw==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/postcss-preset-env": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-8.5.0.tgz", - "integrity": "sha512-aqAbT5dXqYX5ZvicGKQpaW/eDEZFRfnhV6Hn1Jn2bCKEB9L2MgsTdnIsXsZyFUQflIV2wIs9HTEQgkH5duMCNg==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "dependencies": { - "@csstools/postcss-cascade-layers": "^3.0.1", - "@csstools/postcss-color-function": "^2.2.3", - "@csstools/postcss-color-mix-function": "^1.0.3", - "@csstools/postcss-font-format-keywords": "^2.0.2", - "@csstools/postcss-gradients-interpolation-method": "^3.0.6", - "@csstools/postcss-hwb-function": "^2.2.2", - "@csstools/postcss-ic-unit": "^2.0.4", - "@csstools/postcss-is-pseudo-class": "^3.2.1", - "@csstools/postcss-logical-float-and-clear": "^1.0.1", - "@csstools/postcss-logical-resize": "^1.0.1", - "@csstools/postcss-logical-viewport-units": "^1.0.3", - "@csstools/postcss-media-minmax": "^1.0.3", - "@csstools/postcss-media-queries-aspect-ratio-number-values": "^1.0.3", - "@csstools/postcss-nested-calc": "^2.0.2", - "@csstools/postcss-normalize-display-values": "^2.0.1", - "@csstools/postcss-oklab-function": "^2.2.3", - "@csstools/postcss-progressive-custom-properties": "^2.3.0", - "@csstools/postcss-relative-color-syntax": "^1.0.2", - "@csstools/postcss-scope-pseudo-class": "^2.0.2", - "@csstools/postcss-stepped-value-functions": "^2.1.1", - "@csstools/postcss-text-decoration-shorthand": "^2.2.4", - "@csstools/postcss-trigonometric-functions": "^2.1.1", - "@csstools/postcss-unset-value": "^2.0.1", - "autoprefixer": "^10.4.14", - "browserslist": "^4.21.5", - "css-blank-pseudo": "^5.0.2", - "css-has-pseudo": "^5.0.2", - "css-prefers-color-scheme": "^8.0.2", - "cssdb": "^7.6.0", - "postcss-attribute-case-insensitive": "^6.0.2", - "postcss-clamp": "^4.1.0", - "postcss-color-functional-notation": "^5.1.0", - "postcss-color-hex-alpha": "^9.0.2", - "postcss-color-rebeccapurple": "^8.0.2", - "postcss-custom-media": "^9.1.4", - "postcss-custom-properties": "^13.2.0", - "postcss-custom-selectors": "^7.1.3", - "postcss-dir-pseudo-class": "^7.0.2", - "postcss-double-position-gradients": "^4.0.4", - "postcss-focus-visible": "^8.0.2", - "postcss-focus-within": "^7.0.2", - "postcss-font-variant": "^5.0.0", - "postcss-gap-properties": "^4.0.1", - "postcss-image-set-function": "^5.0.2", - "postcss-initial": "^4.0.1", - "postcss-lab-function": "^5.2.3", - "postcss-logical": "^6.2.0", - "postcss-nesting": "^11.3.0", - "postcss-opacity-percentage": "^2.0.0", - "postcss-overflow-shorthand": "^4.0.1", - "postcss-page-break": "^3.0.4", - "postcss-place": "^8.0.1", - "postcss-pseudo-class-any-link": "^8.0.2", - "postcss-replace-overflow-wrap": "^4.0.0", - "postcss-selector-not": "^7.0.1", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/postcss-pseudo-class-any-link": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-8.0.2.tgz", - "integrity": "sha512-FYTIuRE07jZ2CW8POvctRgArQJ43yxhr5vLmImdKUvjFCkR09kh8pIdlCwdx/jbFm7MiW4QP58L4oOUv3grQYA==", - "dependencies": { - "postcss-selector-parser": "^6.0.10" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/postcss-replace-overflow-wrap": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz", - "integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==", - "peerDependencies": { - "postcss": "^8.0.3" - } - }, - "node_modules/postcss-selector-not": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-7.0.1.tgz", - "integrity": "sha512-1zT5C27b/zeJhchN7fP0kBr16Cc61mu7Si9uWWLoA3Px/D9tIJPKchJCkUH3tPO5D0pCFmGeApAv8XpXBQJ8SQ==", - "dependencies": { - "postcss-selector-parser": "^6.0.10" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.0.13", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", - "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", - "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==" - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "peer": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, - "node_modules/property-expr": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.5.tgz", - "integrity": "sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA==" - }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, - "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", - "peer": true, - "engines": { - "node": ">=6" - } - }, - "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==", - "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/react": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", - "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", - "dependencies": { - "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-datepicker": { - "version": "4.14.0", - "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-4.14.0.tgz", - "integrity": "sha512-MLky2SF8hVTPgFRseauoOprjz6/rUMWq8MHadWYwExJvojUyCZOWDMWq9bRqoliQqqPhcViYjyxAxvFQpD9aDA==", - "dependencies": { - "@popperjs/core": "^2.9.2", - "classnames": "^2.2.6", - "date-fns": "^2.24.0", - "prop-types": "^15.7.2", - "react-onclickoutside": "^6.12.2", - "react-popper": "^2.3.0" - }, - "peerDependencies": { - "react": "^16.9.0 || ^17 || ^18", - "react-dom": "^16.9.0 || ^17 || ^18" - } - }, - "node_modules/react-dom": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", - "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", - "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.0" - }, - "peerDependencies": { - "react": "^18.2.0" - } - }, - "node_modules/react-fast-compare": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz", - "integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==" - }, - "node_modules/react-icons": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.9.0.tgz", - "integrity": "sha512-ijUnFr//ycebOqujtqtV9PFS7JjhWg0QU6ykURVHuL4cbofvRCf3f6GMn9+fBktEFQOIVZnuAYLZdiyadRQRFg==", - "peerDependencies": { - "react": "*" - } - }, - "node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, - "node_modules/react-onclickoutside": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/react-onclickoutside/-/react-onclickoutside-6.13.0.tgz", - "integrity": "sha512-ty8So6tcUpIb+ZE+1HAhbLROvAIJYyJe/1vRrrcmW+jLsaM+/powDRqxzo6hSh9CuRZGSL1Q8mvcF5WRD93a0A==", - "funding": { - "type": "individual", - "url": "https://github.com/Pomax/react-onclickoutside/blob/master/FUNDING.md" - }, - "peerDependencies": { - "react": "^15.5.x || ^16.x || ^17.x || ^18.x", - "react-dom": "^15.5.x || ^16.x || ^17.x || ^18.x" - } - }, - "node_modules/react-popper": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.3.0.tgz", - "integrity": "sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q==", - "dependencies": { - "react-fast-compare": "^3.0.1", - "warning": "^4.0.2" - }, - "peerDependencies": { - "@popperjs/core": "^2.0.0", - "react": "^16.8.0 || ^17 || ^18", - "react-dom": "^16.8.0 || ^17 || ^18" - } - }, - "node_modules/react-popper/node_modules/react-fast-compare": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", - "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==" - }, - "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/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/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" - }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", - "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "functions-have-names": "^1.2.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", - "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", - "dependencies": { - "is-core-module": "^2.11.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/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/resolve-pkg-maps": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", - "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "peer": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/run-applescript": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", - "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==", - "dependencies": { - "execa": "^5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/run-applescript/node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/run-applescript/node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/run-applescript/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/run-applescript/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/run-applescript/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/run-applescript/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/run-applescript/node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "engines": { - "node": ">=6" - } - }, - "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==", - "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/safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "is-regex": "^1.1.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/scheduler": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", - "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", - "dependencies": { - "loose-envify": "^1.1.0" - } - }, - "node_modules/semver": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz", - "integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "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==", - "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==", - "engines": { - "node": ">=8" - } - }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "engines": { - "node": ">=8" - } - }, - "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/string.prototype.matchall": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz", - "integrity": "sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "regexp.prototype.flags": "^1.4.3", - "side-channel": "^1.0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trim": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", - "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", - "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", - "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "peer": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "peer": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/styled-jsx": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", - "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", - "dependencies": { - "client-only": "0.0.1" - }, - "engines": { - "node": ">= 12.0.0" - }, - "peerDependencies": { - "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "babel-plugin-macros": { - "optional": true - } - } - }, - "node_modules/sucrase": { - "version": "3.32.0", - "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.32.0.tgz", - "integrity": "sha512-ydQOU34rpSyj2TGyz4D2p8rbktIOZ8QY9s+DGLvFU1i5pWJE8vkpruCjGCMHsdXwnD7JDcS+noSwM/a7zyNFDQ==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.2", - "commander": "^4.0.0", - "glob": "7.1.6", - "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": ">=8" - } - }, - "node_modules/sucrase/node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "peer": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "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==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/synckit": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz", - "integrity": "sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==", - "dependencies": { - "@pkgr/utils": "^2.3.1", - "tslib": "^2.5.0" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, - "node_modules/tailwindcss": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.2.tgz", - "integrity": "sha512-9jPkMiIBXvPc2KywkraqsUfbfj+dHDb+JPWtSJa9MLFdrPyazI7q6WX2sUrm7R9eVR7qqv3Pas7EvQFzxKnI6w==", - "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.2.12", - "glob-parent": "^6.0.2", - "is-glob": "^4.0.3", - "jiti": "^1.18.2", - "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", - "postcss-value-parser": "^4.2.0", - "resolve": "^1.22.2", - "sucrase": "^3.32.0" - }, - "bin": { - "tailwind": "lib/cli.js", - "tailwindcss": "lib/cli.js" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/tailwindcss/node_modules/postcss-load-config": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.1.tgz", - "integrity": "sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==", - "dev": true, - "dependencies": { - "lilconfig": "^2.0.5", - "yaml": "^2.1.1" - }, - "engines": { - "node": ">= 14" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": ">=8.0.9", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "postcss": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, - "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "peer": true - }, - "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/tiny-case": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tiny-case/-/tiny-case-1.0.3.tgz", - "integrity": "sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==" - }, - "node_modules/tiny-warning": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", - "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" - }, - "node_modules/titleize": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz", - "integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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==", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toposort": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", - "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==" - }, - "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/tsconfig-paths": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", - "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } - }, - "node_modules/tslib": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz", - "integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==" - }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "peer": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", - "dependencies": { - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typescript": { - "version": "4.9.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", - "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/unfetch": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unfetch/-/unfetch-5.0.0.tgz", - "integrity": "sha512-3xM2c89siXg0nHvlmYsQ2zkLASvVMBisZm5lF3gFDqfF2xonNStDJyMpvaOBe0a1Edxmqrf2E0HBdmy9QyZaeg==" - }, - "node_modules/untildify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", - "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", - "engines": { - "node": ">=8" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", - "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", - "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.1", - "picocolors": "^1.0.0" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "peer": true, - "dependencies": { - "punycode": "^2.1.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==" - }, - "node_modules/warning": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", - "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", - "dependencies": { - "loose-envify": "^1.0.0" - } - }, - "node_modules/web-streams-polyfill": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", - "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", - "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/yaml": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz", - "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==", - "dev": true, - "engines": { - "node": ">= 14" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yup": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/yup/-/yup-1.2.0.tgz", - "integrity": "sha512-PPqYKSAXjpRCgLgLKVGPA33v5c/WgEx3wi6NFjIiegz90zSwyMpvTFp/uGcVnnbx6to28pgnzp/q8ih3QRjLMQ==", - "dependencies": { - "property-expr": "^2.0.5", - "tiny-case": "^1.0.3", - "toposort": "^2.0.2", - "type-fest": "^2.19.0" - } - }, - "node_modules/yup/node_modules/type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - } -} diff --git a/Frontend/package.json b/Frontend/package.json deleted file mode 100644 index f469fd2..0000000 --- a/Frontend/package.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "name": "alumni-portal", - "version": "0.1.0", - "private": true, - "scripts": { - "dev": "next", - "build": "next build", - "start": "next start", - "lint": "next lint" - }, - "dependencies": { - "@next/font": "13.1.4", - "@types/node": "18.11.18", - "@types/react": "18.0.27", - "@types/react-dom": "18.0.10", - "axios": "^1.3.5", - "eslint-config-next": "13.1.4", - "formik": "^2.4.2", - "isomorphic-unfetch": "^4.0.2", - "next": "13.1.4", - "postcss-preset-env": "^8.0.1", - "react": "18.2.0", - "react-datepicker": "^4.11.0", - "react-dom": "18.2.0", - "react-icons": "^4.8.0", - "typescript": "4.9.4", - "yup": "^1.2.0" - }, - "devDependencies": { - "@types/react-datepicker": "^4.11.2", - "autoprefixer": "^10.4.13", - "postcss": "^8.4.21", - "tailwindcss": "^3.2.6" - } -} diff --git a/Frontend/postcss.config.js b/Frontend/postcss.config.js deleted file mode 100644 index 4660c1a..0000000 --- a/Frontend/postcss.config.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - plugins: [ - 'tailwindcss', - 'postcss-preset-env', - ], -} \ No newline at end of file diff --git a/Frontend/requirements.txt b/Frontend/requirements.txt deleted file mode 100644 index efecf23..0000000 --- a/Frontend/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -protobuf==4.21.12 -pywatchman==1.4.1 diff --git a/Frontend/src/components/features/avatar.tsx b/Frontend/src/components/features/avatar.tsx deleted file mode 100644 index e98a01e..0000000 --- a/Frontend/src/components/features/avatar.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import React from "react"; - -const Avatar = ({ src, alt, size = 64 }) => { - return ( -
- {alt} -
- ); -}; - -export default Avatar; \ No newline at end of file diff --git a/Frontend/src/components/features/editprofile.tsx b/Frontend/src/components/features/editprofile.tsx deleted file mode 100644 index 734f616..0000000 --- a/Frontend/src/components/features/editprofile.tsx +++ /dev/null @@ -1,234 +0,0 @@ -import React, { useEffect, useState } from "react"; -import Avatar from "./avatar"; -import axios from 'axios'; -import { apiEndPoint } from "../../constants"; -import { HiUserCircle } from "react-icons/hi"; - -const EditProfileModal = ({ onSave, onClose }) => { - const [user, setUser] = useState({ - name: null, - bio: null, - // profilePic: null, - name_russian: null, - telegram: null, - graduation_year: null, - field_of_study: null, - city: null, - company: null, - position: null, - }); - - const [successMessage, setSuccessMessage] = useState(''); - const [errorMessage, setErrorMessage] = useState(''); - const [serverError, setServerError] = useState(''); - const [showModal, setShowModal] = useState(false); - const [token, setToken] = useState(''); - - const updateUserProfile = async (token: string | null) => { - await axios.post(`${apiEndPoint}/update`, - JSON.stringify({ - name: user.name, - name_russian: user.name_russian, - telegram: user.telegram, - graduation_year: user.graduation_year, - field_of_study: user.field_of_study, - bio: user.bio, - city: user.city, - company: user.company, - position: user.position, - }), - { - withCredentials: true, - headers: { - 'Content-Type': 'application/json', - 'Authorization': `TOKEN ${token}`, - } - }, - ) - .then(res => { - if(res.status === 201 || 200) { - setSuccessMessage(res.data.status); - setShowModal(true); - }else { - throw new Error('Could not connect to the server'); - } - - }).catch(function(err) { - if(err.response && err.response.status === 400 || 402) { - setErrorMessage(err.response.data.status); - }else if(err.response && err.response.status === 500) { - setServerError(err.response.statusText); - setShowModal(true); - }else { - setServerError(err.message); - setShowModal(true); - } - }) - } - - useEffect(() => { - const token = localStorage.getItem("alumni-token"); - setToken(token); - updateUserProfile(token); - }, []); - - const handleOnChange = (value: any, id: string) => { - let newUserProfile = { ...user }; - newUserProfile[id] = value; - setUser(newUserProfile); - } - - const handleSave = () => { - // const updatedUser = user; - onSave(user); -}; - - return ( -
-
-
-
-
- - ​ -
-
-
- { - user.profilePic ? - : -
- } -
-

Edit Profile

-
-
- {/* */} - handleOnChange(e.target.value, 'name')} - /> -
-
- {/* */} - handleOnChange(e.target.value, 'name_russian')} - /> -
-
- {/* */} - handleOnChange(e.target.value, 'field_of_study')} - /> -
-
- {/* */} - handleOnChange(Math.abs(parseInt(e.target.value)), 'graduation_year')} - onKeyDown={e => (e.key === '-' || e.key === '+') && e.preventDefault()} - /> -
-
- {/* */} - handleOnChange(e.target.value, 'field_of_study')} - /> -
-
- {/* */} - handleOnChange(e.target.value, 'position')} - /> -
-
- {/* */} - handleOnChange(e.target.value, 'telegram')} - /> -
-
- {/* */} - handleOnChange(e.target.value, 'city')} - /> -
-
- {/* */} -