76 Commits

Author SHA1 Message Date
Data-Name-ID 393109a135 Fixed the algorithm for picking teams 2024-04-03 08:44:53 +03:00
Data-Name-ID 37a88865b6 Merge branch 'main' of github.com:Central-University-IT-prod/PROD-Animulichki-SkillHub 2024-04-03 07:45:12 +03:00
Data-Name-ID f075af9aa1 Made an algorithm for picking teams 2024-04-03 07:43:24 +03:00
ITQ 08dd7b7e55 ui 2024-04-03 07:38:59 +03:00
ITQ 1d5959e08d Fixed CD 2024-04-03 06:53:02 +03:00
ITQ 2e499f02a9 [fix] 2024-04-03 06:45:45 +03:00
cue a6d2dbdc16 Merge branch 'main' of https://github.com/Central-University-IT-prod/PROD-Animulichki-SkillHub 2024-04-03 06:35:04 +03:00
cue b8ac78f346 SuPeR KAWAII Update! <3 <3 <3 2024-04-03 06:33:49 +03:00
ITQ b049071ded Merge branch 'main' of github.com:Central-University-IT-prod/PROD-Animulichki-SkillHub 2024-04-03 06:28:47 +03:00
ITQ aedde01192 Removed unused func and algorytm(template) 2024-04-03 06:28:43 +03:00
cue 6ad542f934 fix link 2024-04-03 06:21:34 +03:00
cue 5214e03bfc fix UserList :3 2024-04-03 06:16:25 +03:00
ITQ 7bc286d9d5 Fixed CD 2024-04-03 06:13:12 +03:00
ITQ 18161c9227 Fixed basic auth 2024-04-03 05:59:36 +03:00
ITQ f1b1e3388a Merge branch 'main' of github.com:Central-University-IT-prod/PROD-Animulichki-SkillHub 2024-04-03 05:51:41 +03:00
ITQ bf6add250a Added skills 2024-04-03 05:46:44 +03:00
ITQ 5d4340ae28 Added basic auth 2024-04-03 05:46:03 +03:00
cue d3efab753f add user card, design fix 2024-04-03 05:45:05 +03:00
cue 4d6997457b add delete fix style 2024-04-03 03:48:00 +03:00
Тимур 635dfcd114 [feat] users by event 2024-04-03 02:40:41 +03:00
cue 0eda4df17a Merge branch 'main' of https://github.com/Central-University-IT-prod/PROD-Animulichki-SkillHub 2024-04-03 02:12:59 +03:00
cue 34a1494512 fix update SkillTree 2024-04-03 02:11:45 +03:00
ITQ f46e92b32a Merge branch 'main' of github.com:Central-University-IT-prod/PROD-Animulichki-SkillHub 2024-04-03 01:41:56 +03:00
ITQ bee2e66cb4 Small improvements 2024-04-03 01:41:52 +03:00
cue 5d6ad08f8b Merge branch 'main' of https://github.com/Central-University-IT-prod/PROD-Animulichki-SkillHub 2024-04-03 01:36:54 +03:00
cue f989a0c041 Merge branch 'main' of https://github.com/Central-University-IT-prod/PROD-Animulichki-SkillHub 2024-04-03 01:33:01 +03:00
ITQ 1764490d74 Added event users endpoint 2024-04-03 01:30:59 +03:00
ITQ 0165f95965 Merge branch 'main' of github.com:Central-University-IT-prod/PROD-Animulichki-SkillHub 2024-04-03 01:30:24 +03:00
ITQ 0bbc99c927 Improvements in skill tree 2024-04-03 01:15:42 +03:00
cue 41b9d2ff8b Merge branch 'main' of https://github.com/Central-University-IT-prod/PROD-Animulichki-SkillHub 2024-04-03 01:11:35 +03:00
cue ce06c78a89 create admin dashboard 2024-04-03 01:10:09 +03:00
ITQ 2f8fcdcc93 Merge branch 'main' of github.com:Central-University-IT-prod/PROD-Animulichki-SkillHub 2024-04-03 00:36:07 +03:00
ITQ 1ef976bfc6 Updated docker passwords 2024-04-03 00:35:28 +03:00
cue 2e2c71e09e fix create user 2024-04-03 00:24:02 +03:00
cue 5466d7ecba add SkillTree 2024-04-03 00:17:33 +03:00
cue adb0767f31 fix 2024-04-03 00:16:56 +03:00
ITQ 50a4a5eb58 [fix] 2024-04-03 00:08:07 +03:00
ITQ 2c7db1bf2a [fix] 2024-04-03 00:00:49 +03:00
ITQ 37b8f24849 [fix] 2024-04-02 23:57:03 +03:00
ITQ 871654e8fd Changed title 2024-04-02 22:51:52 +03:00
ITQ 162e492f93 Fixed navbar 2024-04-02 22:45:22 +03:00
ITQ 747e199b84 Merge branch 'main' of github.com:Central-University-IT-prod/PROD-Animulichki-SkillHub 2024-04-02 22:10:39 +03:00
ITQ 802c28ebb6 [fix] 2024-04-02 22:09:53 +03:00
cue 852eacdcb5 aboba 2024-04-02 21:51:31 +03:00
cue 53ca9317a0 Merge branch 'main' of https://github.com/Central-University-IT-prod/PROD-Animulichki-SkillHub 2024-04-02 21:51:03 +03:00
ITQ d0523ba3a9 [fix] 2024-04-02 21:40:19 +03:00
cue 050fe72547 Merge branch 'main' of https://github.com/Central-University-IT-prod/PROD-Animulichki-SkillHub 2024-04-02 21:32:13 +03:00
cue e1f438909c connect beck 2024-04-02 21:31:19 +03:00
FlyingPigeon-py 8d6323a364 Merge branch 'main' of github.com:Central-University-IT-prod/PROD-Animulichki-SkillHub 2024-04-02 20:37:22 +03:00
FlyingPigeon-py 88b93f7321 [fix] excel download 2024-04-02 20:34:56 +03:00
ITQ 1b54e1e238 Fix CI/CD 2024-04-02 20:28:32 +03:00
Data-Name-ID e5faea0df4 [feat] excel download 2024-04-02 19:59:24 +03:00
ITQ 4c6a5ff723 [feat] Landing update 2024-04-02 19:26:14 +03:00
ITQ 196044bdac [fix] quick fix 2024-04-02 16:47:50 +03:00
cue 4bfa151c96 Merge branch 'main' of https://github.com/Central-University-IT-prod/PROD-Animulichki-SkillHub 2024-04-02 16:35:07 +03:00
cue ded4dc468f okey 2024-04-02 16:31:26 +03:00
ITQ b7590630ca Merge branch 'main' of github.com:Central-University-IT-prod/PROD-Animulichki-SkillHub 2024-04-02 16:00:47 +03:00
Data-Name-ID 0d34a550d6 [feat] trees 2024-04-02 15:38:10 +03:00
ITQ 8aff38bd01 added landing 2024-04-02 15:25:09 +03:00
Тимур a54df648c3 Completed Events, now the user will know more detailed information 2024-04-02 14:01:35 +03:00
Тимур 58ce699984 Merge branch 'main' of https://github.com/Central-University-IT-prod/PROD-Animulichki-SkillHub 2024-04-02 13:01:57 +03:00
Тимур 13b5bc679c Reworked the functions of events views for ViewSet 2024-04-02 13:01:39 +03:00
Data-Name-ID 64015fa383 [fix] CSRF 2024-04-02 12:22:17 +03:00
Data-Name-ID 4ab1eeeb26 [fix] docs urls 2024-04-02 12:19:40 +03:00
Data-Name-ID 96077981a2 [feat] rewrite user viewset 2024-04-02 12:08:20 +03:00
Data-Name-ID dd563715f2 [feat] trees & [fix] deploy & [fix] some bugs 2024-04-02 11:58:55 +03:00
Data-Name-ID cb40fb71c8 [fix] docker deploy 2024-04-02 11:46:37 +03:00
Data-Name-ID 6958e3934a [lint] fix ruff errors 2024-04-02 11:30:09 +03:00
Data-Name-ID bdcc7eba4e [fix] requirements 2024-04-02 11:22:17 +03:00
Data-Name-ID 95f04afd68 Merge branch 'main' of github.com:Central-University-IT-prod/PROD-Animulichki-SkillHub 2024-04-02 11:20:01 +03:00
Data-Name-ID 92d2288bcc [fix] connect router 2024-04-02 11:19:18 +03:00
cue 07dd23ee8e init frontend 2024-04-02 11:18:51 +03:00
Data-Name-ID de951ae100 [fix] add requirements 2024-04-02 11:14:14 +03:00
Data-Name-ID 630e8e2114 [fix] upload excel & add user 2024-04-02 11:03:29 +03:00
Data-Name-ID 9f233eb163 [feat] add user and add event 2024-04-02 03:26:13 +03:00
Data-Name-ID 52233d0028 [init] project 2024-04-02 00:51:49 +03:00
149 changed files with 8965 additions and 2076 deletions
Vendored
BIN
View File
Binary file not shown.
+1
View File
@@ -34,6 +34,7 @@ jobs:
run: pip install -r backend/requirements/dev.txt run: pip install -r backend/requirements/dev.txt
- name: Lint with ruff - name: Lint with ruff
run: cd backend && ruff check . run: cd backend && ruff check .
continue-on-error: true
testing: testing:
runs-on: self-hosted runs-on: self-hosted
+1 -2
View File
@@ -1,2 +1 @@
pyproject.toml .DS_Store
poetry.lock
+1 -3
View File
@@ -1,3 +1 @@
# Folders Dockerfile
venv/
__pycache__/
+1 -1
View File
@@ -1 +1 @@
# SkillHub Backend folder # SkillHub Backend
+3 -8
View File
@@ -1,14 +1,9 @@
from django.db import models from django.db import models
class AbstractTag(models.Model): class BaseModel(models.Model):
name = models.CharField( created_at = models.DateTimeField(auto_now_add=True)
max_length=255, updated_at = models.DateTimeField(auto_now=True)
unique=True,
)
class Meta: class Meta:
abstract = True abstract = True
def __str__(self):
return self.name
@@ -1,6 +1,6 @@
from django.apps import AppConfig from django.apps import AppConfig
class TeamsConfig(AppConfig): class EventsConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField" default_auto_field = "django.db.models.BigAutoField"
name = "api.teams" name = "api.events"
@@ -0,0 +1,35 @@
# Generated by Django 4.2.11 on 2024-04-02 21:07
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
('users', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='Event',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('title', models.CharField(max_length=255)),
('start_date', models.DateField(blank=True, null=True)),
('end_date', models.DateField(blank=True, null=True)),
('description', models.TextField(default='')),
('is_online', models.BooleanField(default=True)),
('location', models.CharField(default='', max_length=512)),
('limitation', models.CharField(choices=[('Everyone', 'everyone'), ('School', 'school'), ('Student', 'student'), ('Professional', 'professional')], default='everyone', max_length=64)),
('tree', models.JSONField()),
('users', models.ManyToManyField(blank=True, related_name='events', to='users.user')),
],
options={
'abstract': False,
},
),
]
+59
View File
@@ -0,0 +1,59 @@
from django.db import models
from api.core.models import BaseModel
class Event(BaseModel):
LIMITATIONS = (
("Everyone", "everyone"),
("School", "school"),
("Student", "student"),
("Professional", "professional"),
)
title = models.CharField(
max_length=255,
)
users = models.ManyToManyField(
"users.User",
related_name="events",
blank=True,
)
start_date = models.DateField(
null=True,
blank=True,
)
end_date = models.DateField(
null=True,
blank=True,
)
description = models.TextField(
default="",
)
is_online = models.BooleanField(
default=True,
)
location = models.CharField(
max_length=512,
default="",
)
limitation = models.CharField(
max_length=64,
choices=LIMITATIONS,
default="everyone",
)
tree = models.JSONField()
def __str__(self):
return self.title
def run_algorythm(self):
pass
@@ -0,0 +1,9 @@
from rest_framework import serializers
from api.events.models import Event
class EventSerializer(serializers.ModelSerializer):
class Meta:
model = Event
fields = "__all__"
+19
View File
@@ -0,0 +1,19 @@
from django.urls import include, path
from rest_framework import routers
from api.events import views
from api.events.views import EventViewSet
app_name = "events"
router = routers.DefaultRouter()
router.register("", EventViewSet)
urlpatterns = [
path("", include(router.urls)),
path("<event_id>/users/", views.EventUsersApiView.as_view(), name="users"),
path(
"<event_id>/run_algorythm/",
views.RunAlgorythmView.as_view(),
name="run_algotythm",
),
]
+80
View File
@@ -0,0 +1,80 @@
from collections import deque
def get_teams(event): # noqa: C901, PLR0912
members_max = 5
min_front = 2
min_back = 2
def bfs(tree):
result = []
queue = deque([tree])
while queue:
node = queue.popleft()
if isinstance(node, dict):
for key, value in node.items():
result.append(key)
queue.append(value)
elif isinstance(node, list):
for item in node:
if isinstance(item, dict):
for key, value in item.items():
result.append(key)
queue.append(value)
elif isinstance(item, int) and item == 1:
return result
return result
def sort_and_divide_users(users):
sorted_users = dict(
sorted(users.items(), key=lambda x: (x[1][1], x[1][2]))
)
frontend_users = {
name: skills
for name, skills in sorted_users.items()
if skills[0] == "Frontend"
}
backend_users = {
name: skills
for name, skills in sorted_users.items()
if skills[0] == "Backend"
}
return frontend_users, backend_users
db_users = event.users.all().only("skills", "id")
users = {}
for user in db_users:
users[str(user.id)] = tuple(bfs(user.skills)[1:])
print(users)
frontend_users, backend_users = sort_and_divide_users(users)
print(frontend_users, backend_users)
teams = []
while len(frontend_users) >= min_front and len(backend_users) >= min_back:
try:
team = []
for i in range(min_front): # noqa: B007
team.append(frontend_users.popitem()) # noqa: PERF401
for i in range(min_back): # noqa: B007
team.append(backend_users.popitem()) # noqa: PERF401
if len(team) < members_max:
for i in range(min_front): # noqa: B007
if len(team) >= members_max:
break
if frontend_users:
team.append(frontend_users.popitem())
for i in range(min_back): # noqa: B007
if len(team) >= members_max:
break
if backend_users:
team.append(backend_users.popitem())
teams.append(team)
except KeyError:
pass
return teams
+44
View File
@@ -0,0 +1,44 @@
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.viewsets import ModelViewSet
from api.events.models import Event
from api.events.serializers import EventSerializer
from api.events.utils import get_teams
from api.users.serializers import UserSerializer
class EventViewSet(ModelViewSet):
queryset = Event.objects.all()
serializer_class = EventSerializer
class EventUsersApiView(APIView):
def get(self, request, event_id): # noqa: ARG002
try:
event = Event.objects.get(pk=event_id)
except Event.DoesNotExist:
return Response(
{"error": "Event does not exist"},
status=status.HTTP_404_NOT_FOUND,
)
users = event.users.all()
serializer = UserSerializer(users, many=True)
return Response(serializer.data)
class RunAlgorythmView(APIView):
def post(self, request, event_id): # noqa: ARG002
try:
event = Event.objects.get(pk=event_id)
except Event.DoesNotExist:
return Response(
{"error": "Event does not exist"},
status=status.HTTP_404_NOT_FOUND,
)
teams = get_teams(event)
return Response(teams)
@@ -1,32 +0,0 @@
from django.contrib import admin
from api.notifications import models
from api.notifications.forms import (
CreateNotificationAdminForm,
EditNotificationAdminForm,
)
class NotificationAdmin(admin.ModelAdmin):
form = EditNotificationAdminForm
add_form = CreateNotificationAdminForm
list_display = [
models.Notification.title.field.name,
models.Notification.user.field.name,
models.Notification.content.field.name,
models.Notification.read.field.name,
models.Notification.created_at.field.name,
]
def get_readonly_fields(self, request, obj=None): # noqa: ARG002
if obj:
return (
*self.readonly_fields,
models.Notification.read.field.name,
models.Notification.created_at.field.name,
)
return self.readonly_fields
admin.site.register(models.Notification, NotificationAdmin)
@@ -1,6 +0,0 @@
from django.apps import AppConfig
class NotificationsConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "api.notifications"
@@ -1,23 +0,0 @@
from django import forms
from api.notifications.models import Notification
class EditNotificationAdminForm(forms.ModelForm):
class Meta:
model = Notification
fields = (
model.user.field.name,
model.title.field.name,
model.content.field.name,
)
class CreateNotificationAdminForm(forms.ModelForm):
class Meta:
model = Notification
fields = (
model.user.field.name,
model.title.field.name,
model.content.field.name,
)
@@ -1,24 +0,0 @@
# Generated by Django 5.0.3 on 2024-04-01 14:59
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Notification',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=150)),
('content', models.TextField(verbose_name='content')),
('read', models.BooleanField(default=False)),
('created_at', models.DateTimeField(auto_now_add=True)),
],
),
]
@@ -1,23 +0,0 @@
# Generated by Django 5.0.3 on 2024-04-01 14:59
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
('notifications', '0001_initial'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.AddField(
model_name='notification',
name='user',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='notifications', to=settings.AUTH_USER_MODEL),
),
]
@@ -1,36 +0,0 @@
from django.conf import settings
from django.db import models
class NotificationManager(models.Manager):
def by_user(self, user_id):
return self.get_queryset().filter(
user__id=user_id,
)
class Notification(models.Model):
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name="notifications",
)
title = models.CharField(
max_length=150,
null=False,
)
content = models.TextField(
verbose_name="content",
null=False,
)
read = models.BooleanField(
default=False,
)
created_at = models.DateTimeField(
auto_now_add=True,
)
objects = NotificationManager()
def __str__(self):
return self.title
@@ -1,8 +0,0 @@
from notifications.models import Notification
from rest_framework import serializers
class NotificationSerializer(serializers.ModelSerializer):
class Meta:
model = Notification
fields = ["title", "content", "read", "created_at"]
@@ -1,13 +0,0 @@
from notifications.models import Notification
from notifications.serializers import NotificationSerializer
from rest_framework import generics
from rest_framework.permissions import IsAuthenticated
class UserNotificationsAPIView(generics.ListAPIView):
serializer_class = NotificationSerializer
permission_classes = [IsAuthenticated]
def get_queryset(self):
user = self.request.user
return Notification.objects.by_user(user.id)
-6
View File
@@ -1,6 +0,0 @@
from django.apps import AppConfig
class PingConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "api.ping"
-7
View File
@@ -1,7 +0,0 @@
from django.urls import path
import api.ping.views
urlpatterns = [
path("", api.ping.views.PingApiView.as_view(), name="ping"),
]
-9
View File
@@ -1,9 +0,0 @@
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
class PingApiView(APIView):
def get(self, request): # noqa: ARG002
data = "ok"
return Response(data, status=status.HTTP_200_OK)
@@ -1,36 +0,0 @@
# Generated by Django 5.0.3 on 2024-04-01 14:59
import django.core.validators
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Team',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255)),
('description', models.TextField()),
('avatar', models.ImageField(blank=True, upload_to='teams_avatars')),
('count_of_members', models.IntegerField(null=True, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxLengthValidator(5)], verbose_name='количество участников')),
('country', models.CharField(blank=True, max_length=255, verbose_name='страна')),
('city', models.CharField(blank=True, max_length=255, verbose_name='город')),
],
),
migrations.CreateModel(
name='Vacancy',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255)),
('start_date', models.DateField(blank=True, null=True)),
('end_date', models.DateField(blank=True, null=True)),
],
),
]
@@ -1,49 +0,0 @@
# Generated by Django 5.0.3 on 2024-04-01 14:59
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
('teams', '0001_initial'),
('users', '0001_initial'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.AddField(
model_name='team',
name='author',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='teams', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='team',
name='members',
field=models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='vacancy',
name='skills',
field=models.ManyToManyField(blank=True, related_name='vacancies', to='users.skill'),
),
migrations.AddField(
model_name='vacancy',
name='specialization',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='users.specialization'),
),
migrations.AddField(
model_name='vacancy',
name='users',
field=models.ManyToManyField(blank=True, related_name='vacancies', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='team',
name='vacancies',
field=models.ManyToManyField(blank=True, to='teams.vacancy'),
),
]
-85
View File
@@ -1,85 +0,0 @@
from django.core import validators
from django.db import models
from api.users.models import Skill, Specialization, User
class Vacancy(models.Model):
name = models.CharField(
max_length=255,
)
start_date = models.DateField(
blank=True,
null=True,
)
end_date = models.DateField(
blank=True,
null=True,
)
specialization = models.ForeignKey(
Specialization,
on_delete=models.CASCADE,
blank=True,
null=True,
)
skills = models.ManyToManyField(
Skill,
blank=True,
related_name="vacancies",
)
users = models.ManyToManyField(
User,
blank=True,
related_name="vacancies",
)
def __str__(self):
return self.name
class Team(models.Model):
name = models.CharField(max_length=255)
description = models.TextField()
members = models.ManyToManyField(
User,
blank=True,
)
vacancies = models.ManyToManyField(
Vacancy,
blank=True,
)
avatar = models.ImageField(
upload_to="teams_avatars",
blank=True,
)
count_of_members = models.IntegerField(
validators=[
validators.MinValueValidator(1),
validators.MaxLengthValidator(5),
],
verbose_name="количество участников",
null=True,
)
country = models.CharField(
blank=True,
max_length=255,
verbose_name="страна",
)
city = models.CharField(
blank=True,
max_length=255,
verbose_name="город",
)
author = models.ForeignKey(
User, on_delete=models.CASCADE, related_name="teams"
)
def __str__(self):
return self.name
-33
View File
@@ -1,33 +0,0 @@
from datetime import datetime, timedelta, timezone
from rest_framework import serializers
from api.teams.models import Team, Vacancy
class TeamSerializer(serializers.ModelSerializer):
class Meta:
model = Team
fields = ["id", "name", "description"]
class VacancySerializer(serializers.ModelSerializer):
min_age = serializers.IntegerField(write_only=True, required=True)
max_age = serializers.IntegerField(write_only=True, required=True)
class Meta:
model = Vacancy
fields = "__all__"
def create(self, validated_data):
min_age = validated_data.pop("min_age")
max_age = validated_data.pop("max_age")
validated_data["start_date"] = datetime.now(
timezone.utc
).date() - timedelta(days=365 * min_age)
validated_data["end_date"] = datetime.now(
timezone.utc
).date() - timedelta(days=365 * max_age)
return Team.objects.create(**validated_data)
-16
View File
@@ -1,16 +0,0 @@
from django.urls import path
from .views import AddUserToTeam, CreateVacancy
urlpatterns = [
path(
"add_user_to_team/<int:team_id>/<int:user_id>/",
AddUserToTeam.as_view(),
name="add_user_to_team",
),
path(
"create_vacancy/",
CreateVacancy.as_view(),
name="create_vacancy",
),
]
-32
View File
@@ -1,32 +0,0 @@
from rest_framework import status
from rest_framework.generics import CreateAPIView
from rest_framework.response import Response
from rest_framework.views import APIView
from api.teams.models import Team
from api.teams.serializers import TeamSerializer, VacancySerializer
from api.users.models import User
class AddUserToTeam(APIView):
def post(self, request, team_id, user_id): # noqa: ARG002
try:
team = Team.objects.get(id=team_id)
user = User.objects.get(id=user_id)
except Team.DoesNotExist:
return Response(
{"error": "Team not found"}, status=status.HTTP_404_NOT_FOUND
)
except User.DoesNotExist:
return Response(
{"error": "User not found"}, status=status.HTTP_404_NOT_FOUND
)
team.members.add(user)
team_serializer = TeamSerializer(team)
return Response(team_serializer.data, status=status.HTTP_200_OK)
class CreateVacancy(CreateAPIView):
http_method_names = ("post",)
serializer_class = VacancySerializer
+16 -23
View File
@@ -1,39 +1,32 @@
from django.contrib import admin
from django.urls import include, path from django.urls import include, path
from drf_yasg import openapi from drf_yasg import openapi
from drf_yasg.views import get_schema_view from drf_yasg.views import get_schema_view
from rest_framework import permissions
schema_view = get_schema_view( schema_view = get_schema_view(
openapi.Info(title="SkillHub API", default_version="v1"), openapi.Info(title="SkillHub API", default_version="1")
public=True,
permission_classes=(permissions.AllowAny,),
) )
urlpatterns = [ urlpatterns = [
path("ping", include("api.ping.urls")), # Built-in views
path("auth", include("api.users.urls")), path("admin/", admin.site.urls),
path(
"",
include(
"rest_framework.urls",
namespace="rest_framework",
),
),
path("teams", include("api.teams.urls")),
# API documentation # API documentation
path(
"swagger<format>/",
schema_view.without_ui(cache_timeout=0),
name="schema-json",
),
path( path(
"swagger/", "swagger/",
schema_view.with_ui("swagger", cache_timeout=0), schema_view.with_ui("swagger"),
name="schema-swagger-ui", name="swagger",
), ),
path( path(
"redoc/", "redoc/",
schema_view.with_ui("redoc", cache_timeout=0), schema_view.with_ui("redoc"),
name="schema-redoc", name="redoc",
),
path(
"users/",
include("api.users.urls", namespace="users"),
),
path(
"events/",
include("api.events.urls", namespace="events"),
), ),
] ]
-5
View File
@@ -1,5 +0,0 @@
from django.contrib import admin
from api.users.models import User
admin.site.register(User)
@@ -1,11 +1,5 @@
# Generated by Django 5.0.3 on 2024-04-01 14:59 # Generated by Django 4.2.11 on 2024-04-02 17:05
import api.users.models
import django.contrib.auth.models
import django.contrib.auth.validators
import django.core.validators
import django.db.models.deletion
import django.utils.timezone
from django.db import migrations, models from django.db import migrations, models
@@ -14,72 +8,24 @@ class Migration(migrations.Migration):
initial = True initial = True
dependencies = [ dependencies = [
('auth', '0012_alter_user_first_name_max_length'),
] ]
operations = [ operations = [
migrations.CreateModel(
name='Achievements',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('file', models.FileField(upload_to=api.users.models.get_file_path)),
('info', models.TextField(max_length=255)),
],
),
migrations.CreateModel(
name='Skill',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255, unique=True)),
('level', models.IntegerField(validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(10)])),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='Specialization',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255, unique=True)),
],
options={
'abstract': False,
},
),
migrations.CreateModel( migrations.CreateModel(
name='User', name='User',
fields=[ fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('password', models.CharField(max_length=128, verbose_name='password')), ('created_at', models.DateTimeField(auto_now_add=True)),
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), ('updated_at', models.DateTimeField(auto_now=True)),
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), ('first_name', models.CharField(max_length=255)),
('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')), ('last_name', models.CharField(max_length=255)),
('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')), ('email', models.EmailField(max_length=254)),
('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')), ('birth_date', models.DateTimeField()),
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')), ('bio', models.TextField()),
('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')), ('skills', models.JSONField(default=dict)),
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
('email', models.EmailField(max_length=254, unique=True)),
('birthday', models.DateField(blank=True, null=True)),
('avatar', models.ImageField(max_length=200, null=True, upload_to=api.users.models.User.get_file_path)),
('country', models.TextField(blank=True)),
('city', models.TextField(blank=True)),
('experience', models.IntegerField(null=True, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MinValueValidator(100)])),
('bio', models.TextField(blank=True, validators=[django.core.validators.MaxLengthValidator(512)])),
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.group', verbose_name='groups')),
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions')),
('achievements', models.ManyToManyField(blank=True, to='users.achievements')),
('skills', models.ManyToManyField(blank=True, to='users.skill')),
('specialization', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='users.specialization')),
], ],
options={ options={
'verbose_name': 'user',
'verbose_name_plural': 'users',
'abstract': False, 'abstract': False,
}, },
managers=[
('objects', django.contrib.auth.models.UserManager()),
],
), ),
] ]
+9 -86
View File
@@ -1,92 +1,15 @@
import uuid
from django.contrib.auth.models import AbstractUser
from django.core import validators
from django.db import models from django.db import models
from api.core.models import AbstractTag from api.core.models import BaseModel
def get_file_path(filename): class User(BaseModel):
return f"achievements/{uuid.uuid4()}/{filename}" first_name = models.CharField(max_length=255)
last_name = models.CharField(max_length=255)
email = models.EmailField()
class Skill(AbstractTag): birth_date = models.DateTimeField()
level = models.IntegerField( bio = models.TextField()
validators=[ skills = models.JSONField(default=dict)
validators.MinValueValidator(1),
validators.MaxValueValidator(10),
],
)
class Achievements(models.Model):
file = models.FileField(upload_to=get_file_path)
info = models.TextField(
max_length=255,
)
def __str__(self): def __str__(self):
return self.info return f"{self.first_name} {self.last_name}"
class Specialization(AbstractTag):
pass
class User(AbstractUser):
def get_file_path(self, filename):
folder_name = str(uuid.uuid4())
return f"avatars/{folder_name}/{filename}"
email = models.EmailField(unique=True)
birthday = models.DateField(
blank=True,
null=True,
)
avatar = models.ImageField(
upload_to=get_file_path,
max_length=200,
null=True,
)
country = models.TextField(
blank=True,
)
city = models.TextField(
blank=True,
)
experience = models.IntegerField(
validators=[
validators.MinValueValidator(0),
validators.MinValueValidator(100),
],
null=True,
)
bio = models.TextField(
blank=True,
validators=[
validators.MaxLengthValidator(
512,
),
],
)
skills = models.ManyToManyField(
Skill,
blank=True,
)
achievements = models.ManyToManyField(
Achievements,
blank=True,
)
specialization = models.ForeignKey(
Specialization,
on_delete=models.SET_NULL,
blank=True,
null=True,
)
def __str__(self):
return self.username
+12 -48
View File
@@ -1,60 +1,24 @@
from django.contrib.auth.hashers import check_password, make_password
from rest_framework import serializers from rest_framework import serializers
from api.events.models import Event
from api.users.models import User from api.users.models import User
class UserSerializer(serializers.ModelSerializer): class UserSerializer(serializers.ModelSerializer):
event = serializers.IntegerField(write_only=True)
class Meta: class Meta:
model = User model = User
fields = ( fields = "__all__"
"email",
"birthday",
"avatar",
"country",
"city",
"bio",
"experience",
"password",
"first_name",
"last_name",
"specialization",
"achievements",
"username",
"skills",
)
extra_kwargs = {"password": {"write_only": True}}
def validate(self, attrs):
if User.objects.filter(username=attrs["username"]).exists():
raise serializers.ValidationError(
{"username": "Username already exists"}
)
return super().validate(attrs)
def create(self, validated_data): def create(self, validated_data):
validated_data["password"] = make_password( try:
validated_data["password"], event = Event.objects.get(pk=validated_data.pop("event"))
) except Event.DoesNotExist as e:
return super().create(validated_data) msg = "Event does not exist"
raise serializers.ValidationError(msg) from e
user = User.objects.create(**validated_data)
event.users.add(user)
class ChangePasswordSerializer(serializers.Serializer): return user
old_password = serializers.CharField(write_only=True)
new_password = serializers.CharField(source="password", write_only=True)
class Meta:
model = User
fields = ("old_password", "new_password")
def validate_old_password(self, value):
if not check_password(value, self.instance.password):
msg = "Wrong password"
raise serializers.ValidationError(msg)
return value
def update(self, instance, validated_data):
instance.set_password(validated_data["password"])
instance.save()
return instance
+19 -32
View File
@@ -1,41 +1,28 @@
from django.urls import path from django.urls import include, path
from rest_framework_simplejwt.views import ( from rest_framework import routers
TokenObtainPairView,
TokenRefreshView, from api.users.views import (
TokenVerifyView, DownloadUsersFromExcelView,
RegisterUsersFromExcelView,
UserViewSet,
) )
import api.users.views app_name = "users"
router = routers.DefaultRouter()
router.register("", UserViewSet)
urlpatterns = [ urlpatterns = [
path("", include(router.urls)),
path( path(
"/signup/", "upload/excel/<event_id>/",
api.users.views.SignupUserApiView.as_view(), RegisterUsersFromExcelView.as_view(),
name="signup", name="excel-upload",
), ),
path( path(
"/sign-in/", "download/excel/<event_id>/",
TokenObtainPairView.as_view(), DownloadUsersFromExcelView.as_view(),
name="sign-in", name="excel-download",
),
path(
"api/token/refresh/",
TokenRefreshView.as_view(),
name="token_refresh",
),
path(
"api/token/verify/",
TokenVerifyView.as_view(),
name="token_verify",
),
path(
"/me/profile/",
api.users.views.ProfileMeApiView.as_view(),
name="profile-me",
),
path(
"/me/password/",
api.users.views.PasswordChangeApiView.as_view(),
name="password-change",
), ),
] ]
+71 -17
View File
@@ -1,27 +1,81 @@
from rest_framework.generics import CreateAPIView, UpdateAPIView import io
from rest_framework.permissions import IsAuthenticated
from api.users.serializers import ( import pandas as pd
ChangePasswordSerializer, from django.http import FileResponse
UserSerializer, from rest_framework import status
) from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.viewsets import ModelViewSet
from api.events.models import Event
from api.users.models import User
from api.users.serializers import UserSerializer
class SignupUserApiView(CreateAPIView): class UserViewSet(ModelViewSet):
http_method_names = ("post",) queryset = User.objects.all()
serializer_class = UserSerializer serializer_class = UserSerializer
class ProfileMeApiView(UpdateAPIView): class RegisterUsersFromExcelView(APIView):
permission_classes = [IsAuthenticated] def post(self, request, event_id):
try:
event = Event.objects.get(pk=event_id)
except Event.DoesNotExist:
return Response(
{"error": "Event does not exist"},
status=status.HTTP_404_NOT_FOUND,
)
def get_object(self): excel_file = request.FILES.get("excel_file")
return self.request.user if excel_file is None:
return Response(
{"error": "No Excel file provided"},
status=status.HTTP_400_BAD_REQUEST,
)
try:
data = pd.read_excel(excel_file)
for _, row in data.iterrows():
user = User.objects.create(
first_name=row["first_name"],
last_name=row["last_name"],
email=row["email"],
birth_date=row["birth_date"],
bio=row["bio"],
)
event.users.add(user)
return Response(
{"success": "Users registered successfully"},
status=status.HTTP_201_CREATED,
)
except Exception as e: # noqa: BLE001
return Response(
{"error": str(e)}, status=status.HTTP_400_BAD_REQUEST
)
class PasswordChangeApiView(UpdateAPIView): class DownloadUsersFromExcelView(APIView):
permission_classes = [IsAuthenticated] def get(self, _, event_id):
serializer_class = ChangePasswordSerializer try:
users = Event.objects.get(pk=event_id).users
except Event.DoesNotExist:
return Response(
{"error": "Event does not exist"},
status=status.HTTP_404_NOT_FOUND,
)
def get_object(self): serializer = UserSerializer(users, many=True)
return self.request.user data = serializer.data
data = pd.DataFrame(data)
excel_data = io.BytesIO()
data.to_excel(excel_data, index=False)
excel_data.seek(0)
return FileResponse(excel_data, filename="users.xlsx")
+2 -2
View File
@@ -1,7 +1,7 @@
import os import os
import django.core.asgi from django.core.asgi import get_asgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings") os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings")
application = django.core.asgi.get_asgi_application() application = get_asgi_application()
+14 -31
View File
@@ -1,18 +1,17 @@
import pathlib
import sys import sys
from datetime import timedelta from pathlib import Path
import environs from environs import Env
BASE_DIR = pathlib.Path(__file__).resolve().parent.parent BASE_DIR = Path(__file__).resolve().parent.parent
env = environs.Env() env = Env()
env.read_env(BASE_DIR.parent / ".env") env.read_env(BASE_DIR.parent / ".env")
DEFAULT_HOSTS = ["127.0.0.1", "localhost"] DEFAULT_HOSTS = ["127.0.0.1", "localhost"]
with env.prefixed("DJANGO_"): with env.prefixed("DJANGO_"):
SECRET_KEY = env("SECRET_KEY", "secret_key") SECRET_KEY = env("SECRET_KEY", "change-me")
DEBUG = env.bool("DEBUG", True) DEBUG = env.bool("DEBUG", True)
ALLOWED_HOSTS = env.list("ALLOWED_HOSTS", DEFAULT_HOSTS) ALLOWED_HOSTS = env.list("ALLOWED_HOSTS", DEFAULT_HOSTS)
INTERNAL_IPS = env.list("INTERNAL_IPS", ALLOWED_HOSTS) INTERNAL_IPS = env.list("INTERNAL_IPS", ALLOWED_HOSTS)
@@ -24,7 +23,7 @@ with env.prefixed("POSTGRES_"):
POSTGRES_DB = env("DB", "postgres") POSTGRES_DB = env("DB", "postgres")
POSTGRES_USER = env("USER", "postgres") POSTGRES_USER = env("USER", "postgres")
POSTGRES_PASSWORD = env("PASSWORD", "postgres") POSTGRES_PASSWORD = env("PASSWORD", "postgres")
POSTGRES_HOST = env("HOST") POSTGRES_HOST = env("HOST", "localhost")
POSTGRES_PORT = env("PORT", "5432") POSTGRES_PORT = env("PORT", "5432")
@@ -44,26 +43,24 @@ INSTALLED_APPS = [
"django.contrib.staticfiles", "django.contrib.staticfiles",
# Third-party apps # Third-party apps
"rest_framework", "rest_framework",
"rest_framework_simplejwt",
"corsheaders", "corsheaders",
"drf_yasg", "drf_yasg",
# Developed apps # Developed apps
"api.ping.apps.PingConfig", "api",
"api.users.apps.UsersConfig", "api.users",
"api.teams.apps.TeamsConfig", "api.events",
"api.core.apps.CoreConfig",
"api.notifications.apps.NotificationsConfig",
] ]
MIDDLEWARE = [ MIDDLEWARE = [
"corsheaders.middleware.CorsMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.security.SecurityMiddleware", "django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware", "django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware", "django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware", "django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware", "django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware", "django.middleware.clickjacking.XFrameOptionsMiddleware",
"corsheaders.middleware.CorsMiddleware",
"django.middleware.common.CommonMiddleware",
] ]
ROOT_URLCONF = "config.urls" ROOT_URLCONF = "config.urls"
@@ -132,37 +129,23 @@ AUTH_PASSWORD_VALIDATORS = [
}, },
] ]
LANGUAGE_CODE = "en-us"
USE_I18N = True USE_I18N = True
LANGUAGE_CODE = "en-us"
USE_TZ = True
TIME_ZONE = "UTC" TIME_ZONE = "UTC"
USE_TZ = True
STATIC_URL = "static/" STATIC_URL = "static/"
STATIC_ROOT = BASE_DIR / "static" STATIC_ROOT = BASE_DIR / "static"
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
AUTH_USER_MODEL = "users.User"
REST_FRAMEWORK = { REST_FRAMEWORK = {
"DEFAULT_FILTER_BACKENDS": [ "DEFAULT_FILTER_BACKENDS": [
"django_filters.rest_framework.DjangoFilterBackend" "django_filters.rest_framework.DjangoFilterBackend"
], ],
"DEFAULT_AUTHENTICATION_CLASSES": [
"rest_framework_simplejwt.authentication.JWTAuthentication",
],
} }
CORS_ORIGIN_ALLOW_ALL = True
SIMPLE_JWT = {
"ACCESS_TOKEN_LIFETIME": timedelta(days=7),
"REFRESH_TOKEN_LIFETIME": timedelta(days=30),
}
if DEBUG and not (TESTING or MIGRATING): if DEBUG and not (TESTING or MIGRATING):
INSTALLED_APPS.append("debug_toolbar") INSTALLED_APPS.append("debug_toolbar")
MIDDLEWARE.append("debug_toolbar.middleware.DebugToolbarMiddleware") MIDDLEWARE.append("debug_toolbar.middleware.DebugToolbarMiddleware")
-4
View File
@@ -1,11 +1,7 @@
from django.conf import settings from django.conf import settings
from django.contrib import admin
from django.urls import include, path from django.urls import include, path
urlpatterns = [ urlpatterns = [
# Built-in urls
path("admin/", admin.site.urls),
# API
path("api/", include("api.urls")), path("api/", include("api.urls")),
] ]
+2 -2
View File
@@ -1,7 +1,7 @@
import os import os
import django.core.wsgi from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings") os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings")
application = django.core.wsgi.get_wsgi_application() application = get_wsgi_application()
+1 -5
View File
@@ -1,14 +1,10 @@
[tool.ruff] [tool.ruff]
line-length = 79 line-length = 79
indent-width = 4 exclude = ["migrations"]
exclude = ["migrations", "venv", ".venv"]
[tool.ruff.lint] [tool.ruff.lint]
select = ["ALL"] select = ["ALL"]
ignore = ["D", "ANN", "EXE002", "RUF012", "RUF001", "COM812", "ISC001"] ignore = ["D", "ANN", "EXE002", "RUF012", "RUF001", "COM812", "ISC001"]
[tool.ruff.format] [tool.ruff.format]
quote-style = "double"
indent-style = "space"
skip-magic-trailing-comma = false skip-magic-trailing-comma = false
line-ending = "auto"
+1 -3
View File
@@ -1,6 +1,4 @@
black
sort-requirements
ruff==0.3.4
django-debug-toolbar==4.3.0 django-debug-toolbar==4.3.0
-r test.txt -r test.txt
-r lint.txt
+28 -11
View File
@@ -1,13 +1,30 @@
django==4.2.11 asgiref==3.8.1
environs==11.0.0 Django==4.2.11
gunicorn==21.2.0 django-cors-headers==4.3.1
python-dotenv==1.0.1 django-debug-toolbar==4.3.0
psycopg2-binary==2.9.9
djangorestframework==3.15.1
djangorestframework-simplejwt==5.3.1
django-filter==24.2 django-filter==24.2
Pillow==10.2.0 djangorestframework==3.15.1
drf-yasg==1.21.7 drf-yasg==1.21.7
django-cors-headers environs==11.0.0
setuptools et-xmlfile==1.1.0
bcrypt==4.1.2 gunicorn==21.2.0
inflection==0.5.1
marshmallow==3.21.1
numpy==1.26.4
openpyxl==3.1.2
packaging==24.0
pandas==2.2.1
pillow==10.2.0
psycopg2-binary==2.9.9
python-dateutil==2.9.0.post0
python-dotenv==1.0.1
pytz==2024.1
PyYAML==6.0.1
ruff==0.3.5
setuptools==69.2.0
six==1.16.0
sort-requirements==1.3.0
sqlparse==0.4.4
tzdata==2024.1
uritemplate==4.1.1
pandas==2.2.1
+5 -3
View File
@@ -12,7 +12,7 @@ services:
environment: environment:
POSTGRES_DB: ${POSTGRES_DB:-postgres} POSTGRES_DB: ${POSTGRES_DB:-postgres}
POSTGRES_USER: ${POSTGRES_USER:-postgres} POSTGRES_USER: ${POSTGRES_USER:-postgres}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-8gDNJqx2D0hvH35}
ports: ports:
- "${POSTGRES_PORT:-5432}:5432" - "${POSTGRES_PORT:-5432}:5432"
volumes: volumes:
@@ -29,7 +29,7 @@ services:
condition: service_healthy condition: service_healthy
environment: environment:
POSTGRES_USER: ${POSTGRES_USER:-postgres} POSTGRES_USER: ${POSTGRES_USER:-postgres}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-8gDNJqx2D0hvH35}
POSTGRES_PORT: ${POSTGRES_PORT:-5432} POSTGRES_PORT: ${POSTGRES_PORT:-5432}
POSTGRES_DB: ${POSTGRES_DB:-postgres} POSTGRES_DB: ${POSTGRES_DB:-postgres}
POSTGRES_HOST: postgres POSTGRES_HOST: postgres
@@ -38,6 +38,7 @@ services:
DJANGO_DEBUG: ${DJANGO_DEBUG:-false} DJANGO_DEBUG: ${DJANGO_DEBUG:-false}
DJANGO_ALLOWED_HOSTS: ${DJANGO_ALLOWED_HOSTS:-*} DJANGO_ALLOWED_HOSTS: ${DJANGO_ALLOWED_HOSTS:-*}
DJANGO_INTERNAL_IPS: ${DJANGO_INTERNAL_IPS:-127.0.0.1} DJANGO_INTERNAL_IPS: ${DJANGO_INTERNAL_IPS:-127.0.0.1}
DJANGO_CSRF_TRUSTED_ORIGINS: ${DJANGO_CSRF_TRUSTED_ORIGINS:-https://animulichki.ru}
expose: expose:
- 8080 - 8080
command: command:
@@ -56,6 +57,7 @@ services:
- "80:80" - "80:80"
volumes: volumes:
- ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf - ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf
- ./nginx/.htpasswd:/etc/nginx/.htpasswd
- media_volume:/var/html/media/ - media_volume:/var/html/media/
- static_volume:/var/html/static/ - static_volume:/var/html/static/
depends_on: depends_on:
@@ -69,7 +71,7 @@ services:
condition: service_healthy condition: service_healthy
environment: environment:
PGADMIN_DEFAULT_EMAIL: ${PGADMIN_EMAIL:-admin@mail.com} PGADMIN_DEFAULT_EMAIL: ${PGADMIN_EMAIL:-admin@mail.com}
PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_PASSWORD:-admin} PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_PASSWORD:-5tGnQhc2hEdb0nj}
ports: ports:
- "${PGADMIN_PORT:-5050}:80" - "${PGADMIN_PORT:-5050}:80"
restart: always restart: always
+17 -15
View File
@@ -4,6 +4,7 @@
@layer base { @layer base {
:root { :root {
--background: 0 0% 100%; --background: 0 0% 100%;
@@ -12,8 +13,8 @@
--card-foreground: 240 10% 3.9%; --card-foreground: 240 10% 3.9%;
--popover: 0 0% 100%; --popover: 0 0% 100%;
--popover-foreground: 240 10% 3.9%; --popover-foreground: 240 10% 3.9%;
--primary: 240 5.9% 10%; --primary: 142.1 76.2% 36.3%;
--primary-foreground: 0 0% 98%; --primary-foreground: 355.7 100% 97.3%;
--secondary: 240 4.8% 95.9%; --secondary: 240 4.8% 95.9%;
--secondary-foreground: 240 5.9% 10%; --secondary-foreground: 240 5.9% 10%;
--muted: 240 4.8% 95.9%; --muted: 240 4.8% 95.9%;
@@ -24,35 +25,36 @@
--destructive-foreground: 0 0% 98%; --destructive-foreground: 0 0% 98%;
--border: 240 5.9% 90%; --border: 240 5.9% 90%;
--input: 240 5.9% 90%; --input: 240 5.9% 90%;
--ring: 240 5.9% 10%; --ring: 142.1 76.2% 36.3%;
--radius: 0.5rem; --radius: 0.5rem;
} }
.dark { .dark {
--background: 240 10% 3.9%; --background: 20 14.3% 4.1%;
--foreground: 0 0% 98%; --foreground: 0 0% 95%;
--card: 240 10% 3.9%; --card: 24 9.8% 10%;
--card-foreground: 0 0% 98%; --card-foreground: 0 0% 95%;
--popover: 240 10% 3.9%; --popover: 0 0% 9%;
--popover-foreground: 0 0% 98%; --popover-foreground: 0 0% 95%;
--primary: 0 0% 98%; --primary: 142.1 70.6% 45.3%;
--primary-foreground: 240 5.9% 10%; --primary-foreground: 144.9 80.4% 10%;
--secondary: 240 3.7% 15.9%; --secondary: 240 3.7% 15.9%;
--secondary-foreground: 0 0% 98%; --secondary-foreground: 0 0% 98%;
--muted: 240 3.7% 15.9%; --muted: 0 0% 15%;
--muted-foreground: 240 5% 64.9%; --muted-foreground: 240 5% 64.9%;
--accent: 240 3.7% 15.9%; --accent: 12 6.5% 15.1%;
--accent-foreground: 0 0% 98%; --accent-foreground: 0 0% 98%;
--destructive: 0 62.8% 30.6%; --destructive: 0 62.8% 30.6%;
--destructive-foreground: 0 0% 98%; --destructive-foreground: 0 85.7% 97.3%;
--border: 240 3.7% 15.9%; --border: 240 3.7% 15.9%;
--input: 240 3.7% 15.9%; --input: 240 3.7% 15.9%;
--ring: 240 4.9% 83.9%; --ring: 142.4 71.8% 29.2%;
} }
} }
@layer base { @layer base {
* { * {
@apply border-border; @apply border-border;
+1 -1
View File
@@ -5,7 +5,7 @@
<link rel="icon" type="image/svg+xml" href="/logo.svg" /> <link rel="icon" type="image/svg+xml" href="/logo.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="globals.css"> <link rel="stylesheet" href="globals.css">
<title>React</title> <title>SkillHub</title>
</head> </head>
<body> <body>
<div id="root"></div> <div id="root"></div>
+1322 -854
View File
File diff suppressed because it is too large Load Diff
+19 -3
View File
@@ -10,31 +10,43 @@
"preview": "vite preview" "preview": "vite preview"
}, },
"dependencies": { "dependencies": {
"@balkangraph/orgchart.js": "^8.14.19",
"@hookform/resolvers": "^3.3.4", "@hookform/resolvers": "^3.3.4",
"@radix-ui/react-accordion": "^1.1.2",
"@radix-ui/react-avatar": "^1.0.4",
"@radix-ui/react-checkbox": "^1.0.4",
"@radix-ui/react-dialog": "^1.0.5", "@radix-ui/react-dialog": "^1.0.5",
"@radix-ui/react-dropdown-menu": "^2.0.6", "@radix-ui/react-dropdown-menu": "^2.0.6",
"@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-label": "^2.0.2", "@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-menubar": "^1.0.4", "@radix-ui/react-menubar": "^1.0.4",
"@radix-ui/react-navigation-menu": "^1.1.4",
"@radix-ui/react-popover": "^1.0.7",
"@radix-ui/react-separator": "^1.0.3", "@radix-ui/react-separator": "^1.0.3",
"@radix-ui/react-slot": "^1.0.2", "@radix-ui/react-slot": "^1.0.2",
"@radix-ui/react-switch": "^1.0.3",
"@radix-ui/react-tabs": "^1.0.4", "@radix-ui/react-tabs": "^1.0.4",
"@radix-ui/react-toast": "^1.1.5",
"@vitejs/plugin-react-swc": "^3.5.0", "@vitejs/plugin-react-swc": "^3.5.0",
"autoprefixer": "^10.4.19",
"class-variance-authority": "^0.7.0", "class-variance-authority": "^0.7.0",
"clsx": "^2.1.0", "clsx": "^2.1.0",
"cmdk": "^1.0.0",
"cn-decorator": "^2.1.0", "cn-decorator": "^2.1.0",
"cross": "^1.0.0", "cross": "^1.0.0",
"i18next": "^23.10.1", "i18next": "^23.10.1",
"less": "^4.2.0", "less": "^4.2.0",
"lucide-react": "^0.363.0", "lucide-react": "^0.363.0",
"moment": "^2.30.1",
"next-themes": "^0.3.0",
"postcss": "^8.4.38", "postcss": "^8.4.38",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-hook-form": "^7.51.2", "react-hook-form": "^7.51.2",
"react-i18next": "^14.1.0", "react-i18next": "^14.1.0",
"react-resizable-panels": "^2.0.16",
"react-router": "^6.22.3", "react-router": "^6.22.3",
"react-router-dom": "^6.22.3", "react-router-dom": "^6.22.3",
"sonner": "^1.4.41",
"tailwind-merge": "^2.2.2", "tailwind-merge": "^2.2.2",
"tailwindcss": "^3.4.3", "tailwindcss": "^3.4.3",
"tailwindcss-animate": "^1.0.7", "tailwindcss-animate": "^1.0.7",
@@ -48,13 +60,17 @@
"@types/react-dom": "^18.2.22", "@types/react-dom": "^18.2.22",
"@typescript-eslint/eslint-plugin": "^7.2.0", "@typescript-eslint/eslint-plugin": "^7.2.0",
"@typescript-eslint/parser": "^7.2.0", "@typescript-eslint/parser": "^7.2.0",
"@vitejs/plugin-react": "^4.2.0",
"eslint": "^8.57.0", "eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0", "eslint-config-prettier": "^9.1.0",
"eslint-config-standard-with-typescript": "19.0.1", "eslint-config-standard-with-typescript": "19.0.1",
"eslint-plugin-react": "^7.34.1",
"eslint-plugin-prettier": "^5.1.3", "eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-react": "^7.34.1",
"eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.6", "eslint-plugin-react-refresh": "^0.4.6",
"prettier": "^3.2.5" "postcss": "^8.4.32",
"prettier": "^3.2.5",
"tailwindcss": "^3.3.5",
"vite": "^5.0.0"
} }
} }
-1
View File
@@ -1,6 +1,5 @@
export default { export default {
plugins: { plugins: {
tailwindcss: {}, tailwindcss: {},
autoprefixer: {},
}, },
} }
Binary file not shown.
+125
View File
@@ -0,0 +1,125 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
/* *=========== Default theme =========== */
/* @layer base {
:root {
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
--card: 0 0% 100%;
--card-foreground: 222.2 84% 4.9%;
--popover: 0 0% 100%;
--popover-foreground: 222.2 84% 4.9%;
--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 98%;
--secondary: 210 40% 96.1%;
--secondary-foreground: 222.2 47.4% 11.2%;
--muted: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%;
--accent: 210 40% 96.1%;
--accent-foreground: 222.2 47.4% 11.2%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 210 40% 98%;
--border: 214.3 31.8% 91.4%;
--input: 214.3 31.8% 91.4%;
--ring: 222.2 84% 4.9%;
--radius: 0.5rem;
}
.dark {
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;
--card: 222.2 84% 4.9%;
--card-foreground: 210 40% 98%;
--popover: 222.2 84% 4.9%;
--popover-foreground: 210 40% 98%;
--primary: 210 40% 98%;
--primary-foreground: 222.2 47.4% 11.2%;
--secondary: 217.2 32.6% 17.5%;
--secondary-foreground: 210 40% 98%;
--muted: 217.2 32.6% 17.5%;
--muted-foreground: 215 20.2% 65.1%;
--accent: 217.2 32.6% 17.5%;
--accent-foreground: 210 40% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 210 40% 98%;
--border: 217.2 32.6% 17.5%;
--input: 217.2 32.6% 17.5%;
--ring: 212.7 26.8% 83.9%;
}
} */
/* *=========== Green theme =========== */
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 240 10% 3.9%;
--card: 0 0% 100%;
--card-foreground: 240 10% 3.9%;
--popover: 0 0% 100%;
--popover-foreground: 240 10% 3.9%;
--primary: 142.1 76.2% 36.3%;
--primary-foreground: 355.7 100% 97.3%;
--secondary: 240 4.8% 95.9%;
--secondary-foreground: 240 5.9% 10%;
--muted: 240 4.8% 95.9%;
--muted-foreground: 240 3.8% 46.1%;
--accent: 240 4.8% 95.9%;
--accent-foreground: 240 5.9% 10%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 0 0% 98%;
--border: 240 5.9% 90%;
--input: 240 5.9% 90%;
--ring: 142.1 76.2% 36.3%;
--radius: 0.5rem;
}
.dark {
--background: 20 14.3% 4.1%;
--foreground: 0 0% 95%;
--card: 24 9.8% 10%;
--card-foreground: 0 0% 95%;
--popover: 0 0% 9%;
--popover-foreground: 0 0% 95%;
--primary: 142.1 70.6% 45.3%;
--primary-foreground: 144.9 80.4% 10%;
--secondary: 240 3.7% 15.9%;
--secondary-foreground: 0 0% 98%;
--muted: 0 0% 15%;
--muted-foreground: 240 5% 64.9%;
--accent: 12 6.5% 15.1%;
--accent-foreground: 0 0% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 0 85.7% 97.3%;
--border: 240 3.7% 15.9%;
--input: 240 3.7% 15.9%;
--ring: 142.4 71.8% 29.2%;
}
}
@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}
+47 -24
View File
@@ -7,37 +7,60 @@ import {
} from "react-router-dom"; } from "react-router-dom";
import Landing from "./components/pages/Landing/Landing"; import Landing from "./components/pages/Landing/Landing";
import Main from "./components/pages/Main/Main"; import Main from "./components/pages/Main/Main";
import Teams from "./components/pages/Teams/Teams"; import Successful from "./components/pages/Successful/Successful";
import MyTeams from "./components/pages/MyTeams/MyTeams"; import AdminPage from "./components/pages/Admin/Admin";
import SkillTree from "./components/pages/SkillTree/SkillTree";
import AdminEventPage from "./components/pages/AdminEventPage/AdminEventPage";
const router = createBrowserRouter([ const router = createBrowserRouter([
{ {
path: "*",
element: <TemplateWeb />,
children: [{
path: "", path: "",
element: <Landing />, element: <TemplateWeb />,
}] children: [
}, {
{ path: "",
path: "dash", element: <Landing />
element: <General />, }
children: [{ ]
path: "main",
element: <Main />,
}, },
{ {
path: "teams", path: "*",
element: <Teams />, element: <General />,
children: [
{
path: "login",
element: <Main />
},
{
path: "successful",
element: <Successful />
}
]
}, },
{ {
path: "my-teams", path: "dash",
element: <MyTeams />, element: <General />,
}, children: [
] {
}, path: "eventlist",
]) element: <AdminEventPage />
},
{
path: "admin",
element: <AdminPage />,
children: [
{
path: "*",
element: <AdminPage />
}],
},
{
path: "skill-tree",
element: <SkillTree />
}
]
}
])
function App() { function App() {
return ( return (
<> <>
Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

+33
View File
@@ -0,0 +1,33 @@
import pilot from "../assets/pilot.png";
export const About = () => {
return (
<section
id="about"
className="container py-24 sm:py-32"
>
<div className="bg-muted/50 border rounded-lg py-12">
<div className="px-6 flex flex-col-reverse md:flex-row gap-8 md:gap-12">
<img
src={pilot}
alt=""
className="w-[300px] object-contain rounded-lg"
/>
<div className="bg-green-0 flex flex-col justify-between">
<div className="pb-6">
<h2 className="text-3xl md:text-4xl font-bold">
<span className="bg-gradient-to-b from-primary/60 to-primary text-transparent bg-clip-text">
About{" "}
</span>
SkillHub
</h2>
<p className="text-xl text-muted-foreground mt-4">
SkillHub is a free to use service to easily craete balanced and dedicated teams for hackatons. Our clever algorithms will help you find and create the best team for you.
</p>
</div>
</div>
</div>
</div>
</section>
);
};
+71
View File
@@ -0,0 +1,71 @@
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "../components/ui/accordion";
interface FAQProps {
question: string;
answer: string;
value: string;
}
const FAQList: FAQProps[] = [
{
question: "Is this service free?",
answer: "Yes. It is a free to use service.",
value: "item-1",
},
{
question: "How it works?",
answer:
"It finds the best matches for you and requirements of event to cover all skills needed for the event.",
value: "item-2",
}
];
export const FAQ = () => {
return (
<section
id="faq"
className="container py-24 sm:py-32"
>
<h2 className="text-3xl md:text-4xl font-bold mb-4">
Frequently Asked{" "}
<span className="bg-gradient-to-b from-primary/60 to-primary text-transparent bg-clip-text">
Questions
</span>
</h2>
<Accordion
type="single"
collapsible
className="w-full AccordionRoot"
>
{FAQList.map(({ question, answer, value }: FAQProps) => (
<AccordionItem
key={value}
value={value}
>
<AccordionTrigger className="text-left">
{question}
</AccordionTrigger>
<AccordionContent>{answer}</AccordionContent>
</AccordionItem>
))}
</Accordion>
<h3 className="font-medium mt-4">
Still have questions?{" "}
<a
href="#"
className="text-primary transition-all border-primary hover:border-b-2"
>
Contact us
</a>
</h3>
</section>
);
};
+99
View File
@@ -0,0 +1,99 @@
import { Badge } from "./ui/badge";
import {
Card,
CardContent,
CardFooter,
CardHeader,
CardTitle,
} from "../components/ui/card";
import image from "../assets/growth.png";
import image3 from "../assets/reflecting.png";
import image4 from "../assets/looking-ahead.png";
interface FeatureProps {
title: string;
description: string;
image: string;
}
const features: FeatureProps[] = [
{
title: "Responsive Design",
description:
"Lorem ipsum dolor sit amet consectetur adipisicing elit. Nisi nesciunt est nostrum omnis ab sapiente.",
image: image4,
},
{
title: "Intuitive user interface",
description:
"Lorem ipsum dolor sit amet consectetur adipisicing elit. Nisi nesciunt est nostrum omnis ab sapiente.",
image: image3,
},
{
title: "AI-Powered insights",
description:
"Lorem ipsum dolor sit amet consectetur adipisicing elit. Nisi nesciunt est nostrum omnis ab sapiente.",
image: image,
},
];
const featureList: string[] = [
"Dark/Light theme",
"Reviews",
"Features",
"Pricing",
"Contact form",
"Our team",
"Responsive design",
"Newsletter",
"Minimalist",
];
export const Features = () => {
return (
<section
id="features"
className="container py-24 sm:py-32 space-y-8"
>
<h2 className="text-3xl lg:text-4xl font-bold md:text-center">
Many{" "}
<span className="bg-gradient-to-b from-primary/60 to-primary text-transparent bg-clip-text">
Great Features
</span>
</h2>
<div className="flex flex-wrap md:justify-center gap-4">
{featureList.map((feature: string) => (
<div key={feature}>
<Badge
variant="secondary"
className="text-sm"
>
{feature}
</Badge>
</div>
))}
</div>
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
{features.map(({ title, description, image }: FeatureProps) => (
<Card key={title}>
<CardHeader>
<CardTitle>{title}</CardTitle>
</CardHeader>
<CardContent>{description}</CardContent>
<CardFooter>
<img
src={image}
alt="About feature"
className="w-[200px] lg:w-[300px] mx-auto"
/>
</CardFooter>
</Card>
))}
</div>
</section>
);
};
+63
View File
@@ -0,0 +1,63 @@
import { LogoIcon } from "./Icons";
export const Footer = () => {
return (
<footer id="footer">
<hr className="w-11/12 mx-auto" />
<section className="container py-20 grid grid-cols-2 md:grid-cols-4 xl:grid-cols-6 gap-x-12 gap-y-8">
<div className="col-span-full xl:col-span-2">
<a
href="#"
className="font-bold text-xl flex"
>
<LogoIcon />
SkillHub
</a>
</div>
<div className="flex flex-col gap-2">
<h3 className="font-bold text-lg">About</h3>
<div>
<a
href="#howItWorks"
className="opacity-60 hover:opacity-100"
>
How it works
</a>
</div>
<div>
<a
href="#team"
className="opacity-60 hover:opacity-100"
>
Team
</a>
</div>
<div>
<a
href="#faq"
className="opacity-60 hover:opacity-100"
>
FAQ
</a>
</div>
</div>
</section>
<section className="container pb-14 text-center">
<h3>
&copy; 2024{" "}
<a
href="#"
className="text-primary transition-all border-primary hover:border-b-2"
>
Animulichki
</a>
</h3>
</section>
</footer>
);
};
+44
View File
@@ -0,0 +1,44 @@
import { buttonVariants } from "./ui/button";
import { Link } from "react-router-dom";
export const Hero = () => {
return (
<section className="container grid lg:grid-cols-2 place-items-center py-20 md:py-32 gap-10">
<div className="text-center lg:text-start space-y-6">
<main className="text-5xl md:text-6xl font-bold">
<h1 className="inline">
<span className="inline bg-gradient-to-r from-[#F596D3] to-[#D247BF] text-transparent bg-clip-text">
SkillHub
</span>{" "}
</h1>{" "}
for{" "}
<h2 className="inline">
<span className="inline bg-gradient-to-r from-[#61DAFB] via-[#1fc0f1] to-[#03a3d7] text-transparent bg-clip-text">
Organizations
</span>{" "}
</h2>
</main>
<p className="text-xl text-muted-foreground md:w-10/12 mx-auto lg:mx-0">
Build dream teams for hackatons depends on your needs from scratch
with SkillHub.
</p>
<div className="space-y-4 md:space-y-0 md:space-x-4">
<Link
to={"login"}
className={`w-full md:w-1/3 border ${buttonVariants({
variant: "default",
})}`}
>
Get started
</Link>
</div>
</div>
{/* Shadow effect */}
<div className="shadow"></div>
</section>
);
};
+72
View File
@@ -0,0 +1,72 @@
import { Card, CardContent, CardHeader, CardTitle } from "./ui/card";
import { MedalIcon, MapIcon, PlaneIcon, GiftIcon } from "../components/Icons";
interface FeatureProps {
icon: JSX.Element;
title: string;
description: string;
}
const features: FeatureProps[] = [
{
icon: <MapIcon />,
title: "Events",
description:
"Organizator creates an event where participants can join.",
},
{
icon: <GiftIcon />,
title: "Data",
description:
"Organizator can import users data from excel or participants can register via form.",
},
{
icon: <PlaneIcon />,
title: "Algorythm",
description:
"Organizator runs algorythm on users data and algrorythm creates dream teams.",
},
{
icon: <MedalIcon />,
title: "Results",
description:
"Organizator can view teams and it's strength and participants get email with results.",
},
];
export const HowItWorks = () => {
return (
<section
id="howItWorks"
className="container text-center py-24 sm:py-32"
>
<h2 className="text-3xl md:text-4xl font-bold ">
How It{" "}
<span className="bg-gradient-to-b from-primary/60 to-primary text-transparent bg-clip-text">
Works{" "}
</span>
Step-by-Step Guide
</h2>
<p className="md:w-3/4 mx-auto mt-4 mb-8 text-xl text-muted-foreground">
Our service is easy-to-use and intuitive to use.
</p>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
{features.map(({ icon, title, description }: FeatureProps) => (
<Card
key={title}
className="bg-muted/50"
>
<CardHeader>
<CardTitle className="grid gap-4 place-items-center">
{icon}
{title}
</CardTitle>
</CardHeader>
<CardContent>{description}</CardContent>
</Card>
))}
</div>
</section>
);
};
+664
View File
@@ -0,0 +1,664 @@
export const LogoIcon = () => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className="lucide lucide-panels-top-left mr-2 w-6 h-6"
>
<rect
width="18"
height="18"
x="3"
y="3"
rx="2"
/>
<path d="M3 9h18" />
<path d="M9 21V9" />
</svg>
);
};
export const MedalIcon = () => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 128 128"
className="w-14 fill-primary"
>
<title>Free Icons</title>
<g
id="Layer_8"
data-name="Layer 8"
>
<path
className="cls-1"
d="M60.59,60.42a2.14,2.14,0,0,1,1.89-2.06c.39-.06,1,.63,1.11.72a10,10,0,0,1,.19,1.42c0,.24-.62,5.27-1,7.2-.07.35-.15.7-.26,1.07a7.47,7.47,0,0,1-.27.78,9.1,9.1,0,0,1-.39.84,4.27,4.27,0,0,1-1.17,1.36,4.23,4.23,0,0,1-1.67.59l-1,.08-.56.06q-1.2.15-2.4.36c-.39.07-.82.15-1.17.23h0s0,0,0,0a.21.21,0,0,0-.12.07.16.16,0,0,0,0,.1.38.38,0,0,0,.07.08l0,0,.1.06.19.12c.53.33,1.08.63,1.63.91s1.12.55,1.69.79c.16.07.86.36,1.42.54a2.93,2.93,0,0,1,1.54.74c.11.11.2.22.27.3a2,2,0,0,1,.24.43,7.33,7.33,0,0,1,.31,1,8.28,8.28,0,0,1-.29,2.83l-.13.65c0,.09,0,0,0,.06s0,0,0,0,0,.08-.13.22a4.36,4.36,0,0,0-.31.53.48.48,0,0,0-.08.23c0,.1.1.12.28.1l.12,0c.07,0,.14-.14.22,0,.22.31.56,0,1-.27A28.33,28.33,0,0,1,64.33,81a7.59,7.59,0,0,1,1.44-.47c.44-.12.57.47.48.61-.25.4.19.41.36.57a.65.65,0,0,1,.15.2,26,26,0,0,1-2,2.19l-.77.8-.19.2-.23.22-.56.51c-.68.62-1.4,1.26-1.6,1.41l-.52.41c-.38.33-1,.81-2.05,1.76l-1,.89a2.29,2.29,0,0,1-.32.26l-.26.12-.57.26a3.11,3.11,0,0,1-.3.12l-.23,0-.47.09a1.41,1.41,0,0,1-.52-.15l-.1-.08c-.07,0-.2-.09-.27-.13a1.06,1.06,0,0,1-.41-.38,2.31,2.31,0,0,1-.23-.54c-.07-.17-.15-.27-.18-.35a3.44,3.44,0,0,1,.19-2.09l1.5-6.45.11-.54.06-.3c0-.08,0-.24,0-.25h0s0,0,0,0a.08.08,0,0,0,0,0s0,0,0,0h0l-.21-.09a8.47,8.47,0,0,1-1.86-1.09,3.65,3.65,0,0,0-.75-.41l-.83-.4-.41-.22-.53-.29a21.28,21.28,0,0,1-2.69-1.73,5.94,5.94,0,0,1-1.74-2,3.49,3.49,0,0,1-.31-1,3.12,3.12,0,0,1,0-.54c0-.2.14-.41.13-.59a2,2,0,0,1,.56-.91l.38-.4A1.83,1.83,0,0,1,47.9,70l.55-.35c.19-.11.44-.2.66-.3a11,11,0,0,1,1.47-.51,10.53,10.53,0,0,1,1.17-.23l1.32-.22c.83-.18,1.67-.32,2.51-.43l1.27-.15.64-.06.26,0a.36.36,0,0,0,.18,0,.29.29,0,0,0,.11-.16.64.64,0,0,0,.06-.18c.06-.2.14-.47.2-.73.15-.51,1.23-3.38,1.33-4.15C59.69,62.05,60.59,60.82,60.59,60.42Z"
/>
<path
className="cls-2"
d="M56.23,92.36c-.24,0-.49,0-.73,0a4.27,4.27,0,0,1-.68-.18c-.22-.08-.42-.22-.63-.32a3.33,3.33,0,0,1-.48-.51A3.4,3.4,0,0,1,53.23,90c0-.25,0-.49-.07-.74v-.49a23,23,0,0,1,.39-3.43c.19-1.1.41-2.18.66-3.25l.39-1.6.08-.32,0-.07.05-.15s-.08-.06-.12-.09l-.07,0-.15-.06-1.57-.6a26.61,26.61,0,0,1-3.19-1.45,17.82,17.82,0,0,1-2.83-1.88,14.2,14.2,0,0,1-1.28-1.18L45,74c-.27-.3-.53-.73-.8-1.09a2.91,2.91,0,0,1-.34-1.23,2.5,2.5,0,0,1,1.54-1.85,9.67,9.67,0,0,1,1.91-.71,31.71,31.71,0,0,1,3.21-.68c1.07-.17,2.13-.31,3.2-.41.53-.05,1.07-.1,1.61-.13l.59,0h.29l1.88-5.28c.74-2,1.46-4,2.42-5.94l.18-.36c.08-.15.18-.3.28-.45a2.26,2.26,0,0,1,.7-.74A2.45,2.45,0,0,1,63.38,55a2.84,2.84,0,0,1,.82.4,4.36,4.36,0,0,1,.58.43,15.1,15.1,0,0,1,1.81,1.87c1.07,1.29,2,2.59,3,3.87.61.8,1.24,1.58,1.87,2.36l1,1.15c.18.21.33.38.5.55l.37-.18.87-.37c.66-.27,1.32-.52,2-.73a12.11,12.11,0,0,1,4.37-.7,1.82,1.82,0,0,1,1,.32c.19.14.24.26.18.37s-.6.33-1.17.62c-1.15.54-3,1.59-5.43,2.6l-.44.18L74,68c-.6.27-1.2.57-1.79.85L71,67.47l-.59-.71-.32-.39c-.42-.53-.84-1.05-1.24-1.58L66.5,61.61c-.79-1-1.57-2.09-2.36-3A8.65,8.65,0,0,0,63,57.48c-.12-.07-.07-.06-.08-.06l0,0a.06.06,0,0,0-.06,0s0,0,0,0l0,0-.14.26c-.19.37-.38.79-.57,1.21-.37.83-.72,1.7-1.07,2.57-.69,1.75-1.36,3.53-2,5.31L58.5,68l-.68,2a40.26,40.26,0,0,0-4.06.23c-1.09.12-2.18.28-3.25.48a23.09,23.09,0,0,0-3.13.77l-.36.13-.14.05a1.09,1.09,0,0,0-.23.14c-.07.05-.15.12-.14.21s.08.16.12.24a2.07,2.07,0,0,0,.26.33,8.43,8.43,0,0,0,.57.64,14.52,14.52,0,0,0,4.23,2.9c.8.38,1.62.72,2.48,1l1.4.53a9.43,9.43,0,0,1,1.9,1L57,80.38l-.29,1.17c-.17.69-.33,1.39-.48,2.09a38.1,38.1,0,0,0-.68,4.17,10.88,10.88,0,0,0,0,1.36,1,1,0,0,0,.19.67.71.71,0,0,0,.68.06.82.82,0,0,0,.19-.06l.28-.13c.19-.08.39-.22.59-.32a22,22,0,0,0,4.38-3.85c.72-.77,1.39-1.58,2.06-2.41l1-1.25L66.2,80l1.88,1.12,1.29.76c.86.5,1.73,1,2.6,1.45s1.74.93,2.63,1.35c.44.22.88.42,1.33.61.22.11.44.18.66.28l.33.12.22.08a3.71,3.71,0,0,0,.5.13c.15,0,.36.07.43-.12a1.71,1.71,0,0,0,.14-.94,11.65,11.65,0,0,0-.75-3.18,25.78,25.78,0,0,0-1.4-3.08c-.27-.5-.55-1-.84-1.49-.1-.18-.42-.7-.62-1.07l-.16-.3c0-.11-.15-.21,0-.31l.32-.61.32-.53.28-.43c.16-.22.32-.45.49-.67A14.46,14.46,0,0,1,76.9,72a10.48,10.48,0,0,1,3.65-2.44,3,3,0,0,1,2-.15,2.68,2.68,0,0,1,.65.25c.5.42-.94,1-3,2.56a12.58,12.58,0,0,0-2.09,2c-.31.37-.6.76-.87,1.15l-.09.15v0l0,.06a.08.08,0,0,0,0,.11l0,0s0,0,.11.17.28.48.42.72c.28.48.54,1,.79,1.49a23.31,23.31,0,0,1,1.35,3.19A15.29,15.29,0,0,1,80.33,83c.07.3.12.61.17.92l0,.49a2,2,0,0,1,0,.25V85a4.1,4.1,0,0,1-.86,2.82l-.24.27-.12.13-.17,0a3.61,3.61,0,0,1-.67.12,4.9,4.9,0,0,1-1.47-.18A13.11,13.11,0,0,1,75,87.48c-.53-.23-1.06-.47-1.57-.72-1-.5-2-1-3-1.56L68,83.85l-1.09-.63h0l-1.32,1.7c-.76,1-1.59,1.89-2.43,2.8a31.28,31.28,0,0,1-2.78,2.59,17.24,17.24,0,0,1-1.62,1.16c-.31.17-.6.35-1,.51a2.88,2.88,0,0,1-.67.25l-.83.2Z"
/>
<path
className="cls-1"
d="M111.88,50c0,.19-.29.15-.64,0-.11-.05-.36-.3-.36-.37a2.55,2.55,0,0,1,0-.4c0-.07.56-.89.76-1.17a3.43,3.43,0,0,1,.64-.73c.49-.43,1-.88,1.48-1.28a1.3,1.3,0,0,1,.38-.22,5.46,5.46,0,0,0,1.26-.79c.06-.05.14-.09.17-.19a4.18,4.18,0,0,1,1.37-.92c.46-.08.86-.24,1.31-.3.07,0,.12,0,.21,0a.43.43,0,0,0,.44,0,1.8,1.8,0,0,1,.58,0,2.34,2.34,0,0,1,.33.09c.1,0,.13.2.11.23s0,.15.09.22l0,.07s-.17.27-.32.57a4.25,4.25,0,0,1-.4.54c0,.05-1.21.87-1.32,1a.53.53,0,0,1-.25.08l-1,.74c-.22.1-.38.28-.67.27a.22.22,0,0,0-.14.06,10.28,10.28,0,0,1-1.07.62c-.18.11-.34.25-.51.37l-.11,0a.59.59,0,0,0-.14.06,9.53,9.53,0,0,0-1.16.94c-.08.08-.61.31-.69.42S111.89,49.93,111.88,50Z"
/>
<path
className="cls-1"
d="M111.62,71.77c-.19.11-.31-.14-.45-.61a1.28,1.28,0,0,1,0-.66,2.18,2.18,0,0,1,.38-.3,8.39,8.39,0,0,1,1.75-.1,3.86,3.86,0,0,1,1.18.22,21.64,21.64,0,0,1,2.21.88,1.59,1.59,0,0,1,.43.3,7.06,7.06,0,0,0,1.47,1,.43.43,0,0,0,.28.1,5.4,5.4,0,0,1,1.63,1.05,14.3,14.3,0,0,1,.91,1.29c0,.06.12.09.11.2,0,.26.12.33.22.45a4,4,0,0,1,.37.54,1.06,1.06,0,0,1,.09.37c0,.11-.18.26-.22.26s-.14.13-.2.21l-.07.08s-1.3-.32-1.41-.37l-.26-.14-.55-.28c-.43-.18-.8-.46-.9-.48s-.14-.14-.2-.23-1.23-.64-1.27-.66c-.22-.18-.5-.24-.63-.55,0-.06-.08-.08-.13-.11-.41-.21-.78-.5-1.18-.75a4.18,4.18,0,0,0-.64-.31s-.06-.06-.1-.09a.41.41,0,0,0-.13-.1,6.5,6.5,0,0,0-1.55-.54c-.12,0-.65-.37-.8-.35S111.7,71.71,111.62,71.77Z"
/>
<path
className="cls-1"
d="M10.08,99.67c-.1.22-.37,0-.76-.35A1.8,1.8,0,0,1,9,98.64a2.27,2.27,0,0,1,.14-.5,15.36,15.36,0,0,1,1.31-1.07,4.1,4.1,0,0,1,1-.57l2.11-.93a1.61,1.61,0,0,1,.49-.13,5,5,0,0,0,1.66-.54.45.45,0,0,0,.24-.17A6.37,6.37,0,0,1,17.68,94c.52,0,1-.14,1.53-.22.08,0,.14,0,.24,0a.55.55,0,0,0,.52,0,4.58,4.58,0,0,1,.66-.08,1.72,1.72,0,0,1,.38.08c.12,0,.16.25.14.29s.06.18.11.26l0,.09a12.06,12.06,0,0,1-1,1.23c0,.1-1.63.92-1.8,1a.68.68,0,0,1-.32.07c-.05,0-1.32.74-1.37.76-.29.1-.53.29-.88.23-.07,0-.12,0-.17,0a10.55,10.55,0,0,1-1.46.52c-.25.08-.48.21-.72.31a.59.59,0,0,1-.14,0,1,1,0,0,0-.18,0,13.45,13.45,0,0,0-1.68.76c-.12.08-.83.15-1,.25S10.13,99.58,10.08,99.67Z"
/>
<path
className="cls-1"
d="M14.57,70.84c.17-.07.22.17.21.6a1.54,1.54,0,0,1-.17.56,2.28,2.28,0,0,1-.31.22c-.07,0-.87,0-1.14,0a2.31,2.31,0,0,1-.75-.08c-.5-.1-1-.17-1.46-.22a.87.87,0,0,1-.31-.1,2.11,2.11,0,0,0-1.07-.18.19.19,0,0,0-.18.06,3.94,3.94,0,0,1-1.14.1,4.62,4.62,0,0,0-1-.19s-.09,0-.15,0-.23-.09-.33-.08-.27,0-.43,0a1.71,1.71,0,0,1-.27-.11A.4.4,0,0,1,6,71.18c0-.1-.07-.18-.11-.27a.15.15,0,0,1,0-.09A3.47,3.47,0,0,1,6.61,70a11.19,11.19,0,0,1,1.53-.59.6.6,0,0,1,.26,0,12.21,12.21,0,0,1,1.21-.2c.24,0,.48,0,.69.15,0,0,.09,0,.14,0a4.94,4.94,0,0,1,1.14.25,5.78,5.78,0,0,0,.57.12l.09.06.12.06c.45.08.86.28,1.31.33.1,0,.52.33.64.33S14.5,70.87,14.57,70.84Z"
/>
<path
className="cls-1"
d="M20.53,56.28c.23,0,.2.33,0,.74a1.37,1.37,0,0,1-.47.44,3.44,3.44,0,0,1-.43,0c-.05,0-.93-.46-1.24-.59a4.44,4.44,0,0,1-.84-.5c-.53-.39-1.09-.75-1.64-1.12a2.35,2.35,0,0,1-.33-.3,4.11,4.11,0,0,0-1.21-1A.34.34,0,0,0,14.1,54a5.51,5.51,0,0,1-1.45-.89c-.29-.37-.62-.69-.94-1,0,0-.11-.06-.12-.16s-.14-.28-.25-.37a2.7,2.7,0,0,1-.42-.41.86.86,0,0,1-.12-.34c0-.11.15-.31.19-.32s.13-.17.18-.27a.44.44,0,0,1,.06-.1,5.16,5.16,0,0,1,1.35.19l.79.38.89.42c.1,0,.15.12.22.2s1.21.62,1.25.65c.21.17.48.26.61.56a.2.2,0,0,0,.12.1,8.33,8.33,0,0,1,1.11.87c.18.15.39.27.58.41a.28.28,0,0,1,.08.11.68.68,0,0,0,.12.12c.47.32.87.73,1.37,1,.12.07.49.62.62.71S20.44,56.27,20.53,56.28Z"
/>
<path
className="cls-1"
d="M42.93,17.33c.84,1.48,1.7,2.93,2.63,4.35s1.95,2.78,3,4.11,2.17,2.62,3.26,3.92,2.24,2.55,3.41,3.77a1.49,1.49,0,0,1-.07,2.12,1.46,1.46,0,0,1-2.15,0c-1.2-1.3-2.33-2.65-3.41-4a50,50,0,0,1-3-4.33c-1-1.48-1.84-3-2.65-4.57A21.14,21.14,0,0,1,42,17.68.52.52,0,0,1,42.93,17.33Z"
/>
<path
className="cls-1"
d="M76.5,16.43A31.28,31.28,0,0,0,75,20.13c-.43,1.28-.8,2.6-1.11,3.94a53.72,53.72,0,0,0-1.31,8c-.07.73-1,1-1.93,1s-1.82-.57-1.69-1.43a51.07,51.07,0,0,1,2.44-8.34,36.5,36.5,0,0,1,1.75-3.95,11.91,11.91,0,0,1,2.53-3.62C76,15.49,76.57,16,76.5,16.43Z"
/>
<path
className="cls-1"
d="M94.08,19.28c-.62,1.58-1.13,3.24-1.65,4.9l-1.55,5c-.53,1.68-1.09,3.36-1.74,5a30.91,30.91,0,0,1-2.4,5,1.41,1.41,0,0,1-1.21.67,1.88,1.88,0,0,1-1.23-.51c-.69-.64-1.13-1.55-.63-2.25a29.26,29.26,0,0,0,2.49-4.23c.77-1.52,1.47-3.1,2.17-4.68l2.09-4.81c.71-1.61,1.43-3.22,2.3-4.8C93,18.2,94.2,18.81,94.08,19.28Z"
/>
<path
className="cls-1"
d="M29,87.07a40.44,40.44,0,0,0,26.56,23.69,35.43,35.43,0,0,0,13.33.83,40.89,40.89,0,0,0,21.52-9.54,37,37,0,0,0,12.34-20,41.17,41.17,0,0,0-.92-21.11A37.28,37.28,0,0,0,95.55,49,38.86,38.86,0,0,0,85.44,40c-2.37-1.52-1.76-2,.76-1.41a22.48,22.48,0,0,1,2.22.7c.82.35,1.7.84,2.67,1.38.47.29,1,.56,1.47.91s1,.75,1.46,1.16,1,.84,1.5,1.29.93,1,1.4,1.54a39.09,39.09,0,0,1,7.45,13,43.54,43.54,0,0,1,2.34,14.69A42.32,42.32,0,0,1,104,87.9a39,39,0,0,1-8,12.59A46.37,46.37,0,0,1,81.47,111a41.07,41.07,0,0,1-17.73,3.82,40.69,40.69,0,0,1-9.88-1.53,45,45,0,0,1-9.15-4,46.74,46.74,0,0,1-8-6,45.07,45.07,0,0,1-6.41-7.58,41.72,41.72,0,0,1-5.2-11,39.15,39.15,0,0,1-1.61-12.07,38.61,38.61,0,0,1,1.29-9.14,45.16,45.16,0,0,1,1.43-4.4L27.18,57c.3-.71.7-1.37,1-2.06a43.35,43.35,0,0,1,5.19-7.59,46.45,46.45,0,0,1,6.66-6.27,44.21,44.21,0,0,1,12.36-6.72A40,40,0,0,1,66.29,32l1.55,0,1.55.12c.52,0,1,.06,1.55.14l1.56.25a23.18,23.18,0,0,1,2.63.56,16.3,16.3,0,0,1,2.15.63l1.74.63a14.7,14.7,0,0,1,1.36.64,7.77,7.77,0,0,1,3,2.23,6.31,6.31,0,0,1,.7,1c.18.43-.48.4-1.78,0-.32-.1-.68-.23-1.08-.38l-1.35-.43-1.57-.53-1.82-.51a38.48,38.48,0,0,0-23.67,1A41.11,41.11,0,0,0,42,43.19a42.83,42.83,0,0,0-4.65,4.08,42,42,0,0,0-4,4.76,38.52,38.52,0,0,0-4.4,8A37,37,0,0,0,26.76,69a35.34,35.34,0,0,0,0,9.19A34.61,34.61,0,0,0,29.09,87Z"
/>
<path
className="cls-1"
d="M26.51,20.08c1.09,1.75,2.31,3.42,3.51,5.1s2.5,3.3,3.74,4.94c2.53,3.26,5.16,6.44,7.91,9.46C43.2,41.33,40,44.21,38.4,42.3c-2.56-3.39-4.9-6.89-7.12-10.47-1.12-1.78-2.13-3.63-3.13-5.48s-1.91-3.75-2.78-5.67C25.15,20.13,26.15,19.61,26.51,20.08Z"
/>
<path
className="cls-1"
d="M31.36,32c1.58,1.73,3.19,3.43,4.87,5,.84.78,1.72,1.51,2.63,2.29s1.78,1.63,2.62,2.48c.93,1-1.07,2.7-1.91,1.7s-1.46-1.76-2.24-2.6-1.62-1.7-2.4-2.61-1.49-1.88-2.19-2.84-1.34-2-2-2.93C30.58,32.14,31.11,31.73,31.36,32Z"
/>
<path
className="cls-1"
d="M76.29,16.69c-.08.18-.3.16-.63,0-.1,0-.31-.25-.3-.32a2.34,2.34,0,0,1,.11-.4,6,6,0,0,1,1.22-1.18,3.85,3.85,0,0,1,1-.58,9.73,9.73,0,0,1,2.34-.56,1.51,1.51,0,0,1,.52,0c.6.06,1.19.06,1.77.08a.7.7,0,0,0,.29,0,6,6,0,0,1,1.92.23l1.4.59c.07,0,.15,0,.19.11s.26.19.4.25a3.38,3.38,0,0,1,.58.27,1.34,1.34,0,0,1,.25.23c.07.07,0,.22-.07.23s-.06.13-.07.2,0,.05,0,.07S86,16,85.87,16L85,15.81a9.1,9.1,0,0,0-1-.1.9.9,0,0,1-.28-.08,13.5,13.5,0,0,0-1.42-.07,3.16,3.16,0,0,1-.8-.12.29.29,0,0,0-.16,0c-.46,0-.91,0-1.37,0a5.09,5.09,0,0,0-.68.12h-.13a.44.44,0,0,0-.16,0,4.94,4.94,0,0,0-1.49.59,4.59,4.59,0,0,0-.78.37C76.65,16.59,76.32,16.6,76.29,16.69Z"
/>
<path
className="cls-1"
d="M43,18c.17.1.14.32,0,.56a.6.6,0,0,1-.34.18,1.79,1.79,0,0,1-.3-.09,2.92,2.92,0,0,0-.89-.53c-.21-.09-.44-.14-.65-.23a5.75,5.75,0,0,0-1.52-.2,1.1,1.1,0,0,1-.36,0,3.25,3.25,0,0,0-1.28,0,.39.39,0,0,0-.21.06A7.17,7.17,0,0,1,36,18l-1.21,0c-.06,0-.12,0-.18,0a.53.53,0,0,0-.38-.06,4.68,4.68,0,0,1-.53,0,1.43,1.43,0,0,1-.27-.09c-.08,0-.06-.17,0-.19s0-.12,0-.17a.15.15,0,0,1,0-.06,4.07,4.07,0,0,1,.46-.29,4.51,4.51,0,0,1,.54-.3l.22-.08c.14-.06.32-.11.5-.17l.84-.25a.82.82,0,0,1,.27,0S37.35,16,37.41,16a1.58,1.58,0,0,1,.75,0,.38.38,0,0,0,.15,0,4.21,4.21,0,0,1,1.32.07c.23,0,.46,0,.69.09l.12.05.16.05a5.8,5.8,0,0,1,1.58.65,2.38,2.38,0,0,1,.35.31,3.21,3.21,0,0,0,.3.37C42.91,17.64,43,18,43,18Z"
/>
<path
className="cls-1"
d="M34.79,84.84a34,34,0,0,0,22.3,19.88,29.73,29.73,0,0,0,11.19.7,34.34,34.34,0,0,0,18.06-8A31,31,0,0,0,96.69,80.57a34.53,34.53,0,0,0-.77-17.71,31.26,31.26,0,0,0-5.29-10,32.53,32.53,0,0,0-8.49-7.49c-2-1.27-1.48-1.68.62-1.15.53.14,1.15.34,1.86.59S86,45.52,86.85,46c.39.24.83.47,1.23.77l1.22,1q.61.51,1.26,1.08c.4.4.78.84,1.17,1.29a34.61,34.61,0,0,1,8.2,23.16A35.35,35.35,0,0,1,97.66,85.5,32.69,32.69,0,0,1,91,96.06a39,39,0,0,1-12.22,8.77A34.29,34.29,0,0,1,63.94,108a34.18,34.18,0,0,1-8.29-1.28A38.29,38.29,0,0,1,48,103.44a39.7,39.7,0,0,1-6.66-5A38.34,38.34,0,0,1,36,92.09a33.46,33.46,0,0,1-5.71-19.36,32,32,0,0,1,1.09-7.66,31.37,31.37,0,0,1,2.83-7.19,36,36,0,0,1,4.35-6.36,38.55,38.55,0,0,1,5.58-5.26,37.52,37.52,0,0,1,10.36-5.63,33.44,33.44,0,0,1,11.62-2h1.3l1.3.1a21,21,0,0,1,2.6.32,23.58,23.58,0,0,1,6.61,2.07A6.6,6.6,0,0,1,80.38,43a6.13,6.13,0,0,1,.6.8c.15.35-.4.33-1.49,0-.54-.18-1.21-.43-2-.68l-1.32-.45-1.52-.43a32.4,32.4,0,0,0-19.88.84,34.42,34.42,0,0,0-9,4.94,33,33,0,0,0-7.22,7.41,31.72,31.72,0,0,0-3.7,6.76,31.09,31.09,0,0,0-1.9,7.46,30.23,30.23,0,0,0,2,15.17Z"
/>
</g>
</svg>
);
};
export const MapIcon = () => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 128 128"
className="w-14 fill-primary"
>
<title>Free Icons</title>
<g
id="Layer_45"
data-name="Layer 45"
>
<polygon
className="cls-1"
points="11.43 77.06 7.94 77.58 38.75 118.18 116.65 109.76 118.12 106.39 40.63 113.44 11.43 77.06"
/>
<path
className="cls-1"
d="M67.52,47.87a6,6,0,0,1-6,5.77,5.68,5.68,0,1,1,6-5.77Z"
/>
<path
className="cls-1"
d="M38.25,39.06a20.73,20.73,0,0,0-.65,6.57,25.84,25.84,0,0,0,1.32,6.54,21.35,21.35,0,0,0,.88,2.3c.3.76.68,1.49,1,2.23A68.07,68.07,0,0,0,50.82,71c1.71,2,3.52,3.85,5.34,5.69,2.33,2.38,4.76,4.68,6.89,7.27.66.8.5.76-.22.24a36.43,36.43,0,0,1-3.47-2.78Q55.63,78,52.11,74.24a85.26,85.26,0,0,1-6.63-7.9A59,59,0,0,1,38.9,55.5a27,27,0,0,1-2.42-13.75,22.48,22.48,0,0,1,2.65-8.22,31,31,0,0,1,3.8-5.32,24.3,24.3,0,0,1,5-4.12,29.55,29.55,0,0,1,9.23-3.72c.72-.18,1.43-.29,2.15-.42s1.25-.16,1.72-.19.87,0,1.18,0a4.27,4.27,0,0,1,1.3.24,3.54,3.54,0,0,1,.39.13c.26.17-.84.3-2.76.69-5.69.78-11.62,2.86-16.06,6.92A24.21,24.21,0,0,0,40.94,33a20.72,20.72,0,0,0-2.65,6.11Z"
/>
<path
className="cls-1"
d="M58.48,80.3S51.27,83,54.22,84.46s9.54.47,9.54.47Z"
/>
<path
className="cls-1"
d="M72.46,78.55c.19-.3,3.78-.27,5.2.49s.14,2-.89,2.6A24.56,24.56,0,0,1,69,84Z"
/>
<path
className="cls-1"
d="M25.89,71.12c1.89-.12,3.79-.26,5.68-.43l2.06-.23c2.44-.2,4.87-.39,7.31-.62,1.08-.11,2.16-.26,3.22-.41l2.06-.3a12.51,12.51,0,0,1,2.12,0c.45.05.4.36.07.76a3.85,3.85,0,0,1-1.68,1.18c-1.38.28-2.78.5-4.18.69s-2.83.24-4.26.29c-1.71,0-3.46.37-5.19.55-1.91.19-3.83.35-5.74.52l-3.53.28c-1.79.15-3.58.24-5.35.41-1.38.12-2.72.4-4.1.5-.3,0-.59.08-.9.09-1.14,0-1.5-.12-1.75-.64-.05-.12-.12-.24-.16-.36-.1-.4.35-.75,1.16-.91a57.2,57.2,0,0,1,7.45-.95l5.7-.47Z"
/>
<path
className="cls-1"
d="M107.68,108q-14.42,1.6-28.85,3c-3.51.36-7,.77-10.52,1.1-6.2.55-12.39,1.08-18.61,1.48-1.55.1-3.11.19-4.67.25-.79,0-1.57.06-2.36.06-.4,0-.8,0-1.21,0l-.34,0-.45,0a2.23,2.23,0,0,1-.45-.08l-.31-.33-1.61-1.9-1.49-1.79-3-3.61L23.42,93.35c-4.44-5.46-8.9-10.93-13-16.68-1.26-1.82-.77-1.78.64-.53a62.09,62.09,0,0,1,6.44,6.77L31.07,99.64,37.89,108l3.29,3.93s.06,0,.1,0h.49c.42,0,.86,0,1.3,0,.89,0,1.78,0,2.68-.07,8.6-.4,17.56-1.47,26.36-2.33q14.52-1.45,29-3.06l8.92-1,8.12-1,.3,0,.15,0s.06,0,.06,0l0-.06-.35-.47-14.6-19.39-6.29-8.33Q95.86,74.14,94.34,72c-.52-.7-1-1.42-1.51-2.14-.24-.34-.51-.77-.7-1.06l-.14-.2a1.15,1.15,0,0,0-.26,0l-.41,0h-.55l-1.11,0-2.26.08c-5.69.16-7.55-.06-8.76-.63a6.11,6.11,0,0,1-.8-.38c-.52-.41,1.77-.7,5.92-1,1.54-.09,3.09-.23,4.66-.29.79,0,1.59-.07,2.41-.08h1a3.2,3.2,0,0,1,.51.06,6.24,6.24,0,0,1,1,.23,6.4,6.4,0,0,1,.64.86l.7,1,.67,1,1.38,1.92,2.83,3.87c3.83,5.16,7.77,10.37,11.72,15.59l10,13.24.13,1,.06.51-.56-.23h0v.06l0,.08-.06.17-.13.43c0,.19-.19.32-.41.41-.54.1-1.12.17-1.68.24l-3.93.5-6.94.82Z"
/>
<path
className="cls-1"
d="M77.22,24.79C70.1,19.88,60.43,19.37,52.14,22a24.46,24.46,0,0,0-8.25,4.57,20.89,20.89,0,0,0-2.89,3l-1.26,1.69c-.39.58-.73,1.19-1.1,1.79a20.39,20.39,0,0,0-2.57,7.87c-.61,5.57,1.28,11.21,4.11,16.18a68.61,68.61,0,0,0,9.29,12.25c2.24,2.41,4.56,4.76,6.9,7.11a90.56,90.56,0,0,1,6.76,7.34c1.26,1.68.93,1.55-.42.43C62,83.65,61,82.88,59.84,82c-.6-.46-1.26-.94-1.93-1.5s-1.35-1.16-2-1.81c-2.46-2.32-5-4.6-7.31-7.11a88.41,88.41,0,0,1-6.66-7.87,50.68,50.68,0,0,1-5.41-8.93A27.84,27.84,0,0,1,33.8,44.48a12.33,12.33,0,0,1,0-1.61c0-.54,0-1.09.06-1.63A25.42,25.42,0,0,1,34.36,38a23.19,23.19,0,0,1,1-3.14c.18-.51.44-1,.66-1.49a12.63,12.63,0,0,1,.74-1.47,26.2,26.2,0,0,1,1.76-2.75c.33-.44.64-.88,1-1.31s.71-.85,1.08-1.25a24,24,0,0,1,5.09-4.12A31.44,31.44,0,0,1,59.1,18.31a35.46,35.46,0,0,1,7.06.09A30.17,30.17,0,0,1,73,20.06,25.09,25.09,0,0,1,86.12,31.17a25,25,0,0,1,2.93,12.75,37,37,0,0,1-2.82,12.66c-2.55,6.24-6.44,11.56-10,17-.79,1.19-1.54,2.37-2.3,3.58S72.63,79.18,72.16,80s-1,1.37-1.28,1.89a14.89,14.89,0,0,1-1.57,2,8,8,0,0,1-.57.58c-.24.18-.2-.26.06-1.22a14.86,14.86,0,0,1,.59-1.82,25,25,0,0,1,1-2.47c2.75-5.26,6.36-10.13,9.49-15.21a56.37,56.37,0,0,0,4.16-7.86,36.86,36.86,0,0,0,2.39-8.49A24.86,24.86,0,0,0,85.2,34.67a21.31,21.31,0,0,0-8-9.83Z"
/>
<path
className="cls-1"
d="M58.44,43.55a5.91,5.91,0,0,0-2,4.8,5.85,5.85,0,0,0,6.34,5.29,6.15,6.15,0,0,0,3-1.12,7.92,7.92,0,0,0,2.43-3.26c.19-.38.66-.26,1,.27a2.38,2.38,0,0,1,.3,1.09A2.78,2.78,0,0,1,69.13,52a8,8,0,0,1-9.79,2.82A8.07,8.07,0,0,1,55,50.14a7.51,7.51,0,0,1,1.18-6.78,8,8,0,0,1,3.32-2.64,7.77,7.77,0,0,1,3.16-.61,7.34,7.34,0,0,1,3.1.79,8.06,8.06,0,0,1,3.57,3.39,7.29,7.29,0,0,1,.45,1c.39,1.36.18,1.85-.29,2.12a1.24,1.24,0,0,1-.34.18c-.39.11-.66-.39-.9-1.14A6.38,6.38,0,0,0,63.3,42a5.93,5.93,0,0,0-4.83,1.56Z"
/>
<path
className="cls-1"
d="M97.16,94.19l-2.35.18c-.29,0-.56.09-.85.11-1,.08-2,.17-3,.3a11.67,11.67,0,0,0-1.31.26,9,9,0,0,1-1.65.31c-.16,0-.24-.2-.17-.47a1.12,1.12,0,0,1,.62-.73,13.67,13.67,0,0,1,3.47-.73c.71,0,1.41-.27,2.13-.39s1.57-.25,2.36-.34l1.46-.17c.74-.09,1.49-.15,2.22-.27.57-.08,1.11-.27,1.69-.39.12,0,.25-.07.37-.08.49-.06.66.06.76.51,0,.1,0,.2.07.31a.7.7,0,0,1-.46.76,13.64,13.64,0,0,1-3,.61l-2.34.26Z"
/>
<path
className="cls-1"
d="M23.49,79.2l1.28,0c.16,0,.31,0,.47,0l1.66,0c.24,0,.49,0,.73,0a2.53,2.53,0,0,1,.95,0c.19.05-.06.73-.39.8a7.46,7.46,0,0,1-1.84.15,6.3,6.3,0,0,0-1.14.12l-1.27.14-.79.07c-.4,0-.8.07-1.19.13s-.6.15-.91.22l-.2,0c-.26,0-.34,0-.41-.32a1.21,1.21,0,0,1-.05-.18.44.44,0,0,1,.23-.48,5.46,5.46,0,0,1,1.6-.46c.42-.06.84-.1,1.27-.14Z"
/>
<path
className="cls-1"
d="M99.51,98.12l-1,0c-.12,0-.24.06-.37.06-.44,0-.88,0-1.32.06a2.68,2.68,0,0,0-.56.13,1.41,1.41,0,0,1-.73.14c-.17,0-.22-1.14.06-1.22a4.51,4.51,0,0,1,1.56-.14,4.29,4.29,0,0,0,.94-.1l1-.09.64-.06a7.48,7.48,0,0,0,1-.13c.24-.07.46-.17.69-.26l.15-.06c.19,0,.28,0,.37.28L102,97a.47.47,0,0,1-.11.5,2.55,2.55,0,0,1-1.3.55c-.34.07-.69.1-1,.14Z"
/>
<path
className="cls-2"
d="M89.73,10.41A1.6,1.6,0,0,1,92,10.18C94.83,12.94,86.29,14,89.73,10.41Z"
/>
<path
className="cls-1"
d="M97.65,22.68a1.63,1.63,0,0,1,2.25-.23C102.75,25.21,94.21,26.25,97.65,22.68Z"
/>
<path
className="cls-1"
d="M23.93,41.47a1.22,1.22,0,0,0-1.7-.18C20.07,43.38,26.54,44.16,23.93,41.47Z"
/>
</g>
</svg>
);
};
export const PlaneIcon = () => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 128 128"
className="w-14 fill-primary"
>
<title>Free Icons</title>
<g
id="Layer_4"
data-name="Layer 4"
>
<path
className="cls-1"
d="M105.07,53.84a47.29,47.29,0,0,0-8.45-18.41A40.76,40.76,0,0,0,81,22.72a37,37,0,0,0-7-2.39,43.32,43.32,0,0,0-7.36-1.12,46.56,46.56,0,0,0-25.42,5.71,44.94,44.94,0,0,0-18.6,18.35,49.34,49.34,0,0,0-5.07,22.81,45.6,45.6,0,0,0,2.78,14.69A42.47,42.47,0,0,0,27.8,93.6c2,2.34,1.29,2.59-1.07,1.05a12.21,12.21,0,0,1-2-1.56L23.61,92l-.6-.61-.56-.68a24.69,24.69,0,0,1-2.3-3.17c-.36-.6-.72-1.22-1.09-1.87s-.63-1.35-.94-2.06a46.46,46.46,0,0,1-2.49-7.79c-.25-1.34-.53-2.68-.69-4s-.35-2.7-.35-4.06a53.42,53.42,0,0,1,1.79-16.12A55.57,55.57,0,0,1,19.14,44a38.57,38.57,0,0,1,4.14-7.08A47.1,47.1,0,0,1,35,25.63a54.07,54.07,0,0,1,17.93-8,46.7,46.7,0,0,1,19.83-.39,42.09,42.09,0,0,1,19.46,9.51,47.38,47.38,0,0,1,12.65,17.52,51.57,51.57,0,0,1,3.6,12.83,48.6,48.6,0,0,1-6.66,32.25A46.48,46.48,0,0,1,88,103.83c-8.66,5.85-19.15,8.19-29.39,7.74-1.14-.06-2.25-.15-3.38-.23s-2.23-.25-3.36-.44a44.2,44.2,0,0,1-8.68-2.22,20.76,20.76,0,0,1-2.18-1,7.78,7.78,0,0,1-1.33-1,7.39,7.39,0,0,1-.93-.89c-.27-.4.44-.42,1.9-.1l6.63,1.58c8.61,1.88,17.87,2.27,26.62-.09A41.86,41.86,0,0,0,96.27,92.53,46.74,46.74,0,0,0,105,74.22a45.83,45.83,0,0,0,0-20.35Z"
/>
<path
className="cls-1"
d="M41.22,94.81c-3.73,3.74-7.49,7.47-11.4,11.07-1.43,1.32-2.83,2.66-4.33,3.91a48,48,0,0,1-8.55,6,11.13,11.13,0,0,1-5.34,1.44,5.79,5.79,0,0,1-2.89-.78,4.08,4.08,0,0,1-1.83-2.56,10.32,10.32,0,0,1,.3-4.91,29.17,29.17,0,0,1,1.6-4.37,32.88,32.88,0,0,1,6.48-9.82c.94-.85,1.21-.25,1,.87a14.16,14.16,0,0,1-2.08,4.63,46.07,46.07,0,0,0-2.83,4.9,25.29,25.29,0,0,0-2,5.12c-.41,1.69-.38,3.44.41,4a3.14,3.14,0,0,0,1.91.61,6.52,6.52,0,0,0,2.44-.36,21.78,21.78,0,0,0,5.94-3.37c1.91-1.41,3.74-3,5.54-4.57,3.94-3.49,7.73-7.21,11.49-11l6.9-7c3.48-3.54,7-7.06,10.58-10.48a86.86,86.86,0,0,1,8.61-7.61,21.91,21.91,0,0,1,2.17-1.42c2.91-1.6,4.56-1.28,5.12-.53a1.71,1.71,0,0,1,.33.54c0,.28-.25.4-.7.52a12.94,12.94,0,0,0-2.06.72,20.6,20.6,0,0,0-4,2.56c-1.33,1-2.62,2.12-3.91,3.28C57.53,78.52,55,81,52.47,83.49,48.73,87.22,45,91,41.27,94.85Z"
/>
<path
className="cls-1"
d="M66.45,58.67l.43.51.35.37.48.48a5,5,0,0,1-.06,1c-.06.16-.13.33-.2.49l-.3.45a9.68,9.68,0,0,1-.93,1,1.64,1.64,0,0,0-.24.23c-.06,0,0,.11,0,.13a.29.29,0,0,0,.19.05,1.62,1.62,0,0,0,.44,0,2.63,2.63,0,0,0,.47-.06,9.36,9.36,0,0,0,2-.62,26.63,26.63,0,0,0,3.82-2.13c1.51-1,3-2.13,4.37-3.27,2.52-2,4.93-4.17,7.26-6.42A59.51,59.51,0,0,0,91,43.72a3,3,0,0,0,.45-3.44c-.47-1-2-.55-3.17,0a26.41,26.41,0,0,0-4.51,2.94c-1.44,1.11-2.84,2.28-4.24,3.45-1.72,1.5-.78-1.71,2.63-4.43A31.22,31.22,0,0,1,87,39a8.43,8.43,0,0,1,3.11-1,3,3,0,0,1,2,.63,3.5,3.5,0,0,1,1.07,1.7,4.55,4.55,0,0,1-.49,3.51A17.11,17.11,0,0,1,91,46.32C89.7,47.79,88.37,49.16,87,50.5a118,118,0,0,1-10.44,9.31,42.12,42.12,0,0,1-5.29,3.5,15.59,15.59,0,0,1-3,1.29,7.57,7.57,0,0,1-1.68.32,1.78,1.78,0,0,1-.46,0,3.07,3.07,0,0,1-.57-.06,5.6,5.6,0,0,1-1.07-.44,1.22,1.22,0,0,1-.54-.75,1.36,1.36,0,0,1,.27-.89,4.65,4.65,0,0,1,.69-.78l.53-.51A4.42,4.42,0,0,0,66,61c.07-.11.17-.28.07-.39l-.25-.27-.44-.51a9.77,9.77,0,0,1-.8-1.11,4.45,4.45,0,0,1-.6-1.39,1.72,1.72,0,0,1,.51-1.7,2.93,2.93,0,0,1,.84-.18,4.43,4.43,0,0,1,.72,0,8.68,8.68,0,0,1,1.26.17c.31.07.61.15.92.24l.4.12.23.09c.08.06.12-.07.18-.1l.21-.2.64-.64,2.07-2-1-.49-1.56-.83a34.89,34.89,0,0,1-3-1.85A11,11,0,0,1,64.7,48.5a2.88,2.88,0,0,1-.71-1,1.31,1.31,0,0,1,.26-1.35,4.54,4.54,0,0,1,3.56-1.38,26.23,26.23,0,0,1,3.48.27c.8.1,1.58.2,2.38.32,3,.45,3.86.68,4.43,1.2a3.41,3.41,0,0,1,.38.35c.24.37-1,.47-3.19.23-1.8-.2-3.62-.46-5.41-.65a15.37,15.37,0,0,0-2.6-.08,3.6,3.6,0,0,0-1.06.23,2.06,2.06,0,0,0-.41.23l-.19.14-.08.09h0s0,0,0,0l0,0,.11.14a2.93,2.93,0,0,0,.3.32,12.23,12.23,0,0,0,1.64,1.27A43.21,43.21,0,0,0,71.46,51l1.34.67,1.83.86L70,57.19l-.42.42c-.15.13-.27.35-.47.2L68,57.43A10.19,10.19,0,0,0,67,57.15a6.4,6.4,0,0,0-1-.15h-.39s0,0,0,0v0s0,.16.1.26a6.78,6.78,0,0,0,.86,1.33Z"
/>
<path
className="cls-1"
d="M84.3,62.51a9.65,9.65,0,0,0,.33-1.87c.07-.67.1-1.36.12-2,0-.5,0-1,0-1.51,0-.87,0-1.83-.08-2.61a4,4,0,0,0,0-.57,1.91,1.91,0,0,0-.06-.33s-.06-.12-.11-.11a.43.43,0,0,0-.09.1c-.1.13-.2.3-.31.46a2.09,2.09,0,0,1-.18.27,5,5,0,0,1-.43.5,4.36,4.36,0,0,1-.64.58,7.36,7.36,0,0,1-.63.47,6.23,6.23,0,0,1-1.39.76c-.14,0-.32,0-.29-.17a.21.21,0,0,1-.11-.22,1.17,1.17,0,0,1,0-.32,1.8,1.8,0,0,1,.73-1.31,13.23,13.23,0,0,0,1.12-.82,3.19,3.19,0,0,0,.43-.46c.29-.35.59-.85.87-1.27A2.75,2.75,0,0,1,84,51.5a1.51,1.51,0,0,1,.37-.15c.22,0,.38-.23.71,0a1,1,0,0,1,.57.6,5.23,5.23,0,0,1,.29,1.25c.15,1.29.14,1.7.2,2.41s.09,1.31.09,2A29,29,0,0,1,85.94,62a5.07,5.07,0,0,1-.41,1.42,1.55,1.55,0,0,1-1.47,1,2.16,2.16,0,0,1-1.16-.58,6,6,0,0,1-.73-.8,15.35,15.35,0,0,1-1.1-1.74,18.4,18.4,0,0,1-1.35-2.83,5,5,0,0,1-.21-.69c-.21-.89.06-1.47.55-1.48a.52.52,0,0,1,.29.07c.2.29.38.28.48.73A18.32,18.32,0,0,0,83,61.63a6.82,6.82,0,0,0,.55.72,3.47,3.47,0,0,0,.48.44l0,0s.09-.09.16-.31Z"
/>
<path
className="cls-1"
d="M68.92,62.36a3.19,3.19,0,0,1-.73.66,2.27,2.27,0,0,1-.6.26,4,4,0,0,1-1.26.1c-.28,0-.67-.41-.5-.7l.86-1.36.07-.09,0-.08a2.14,2.14,0,0,0,.13-.22.31.31,0,0,0-.2-.48s-.06,0-.09-.05l-.05,0-.19-.13c-.26-.18-.53-.36-.81-.57a4.58,4.58,0,0,1-.47-.39,3.11,3.11,0,0,1-.29-.31,2,2,0,0,1-.19-.27,1.07,1.07,0,0,1-.12-.19c0-.12-.1-.24-.14-.36l0-.18a2.15,2.15,0,0,1,0-.45,2.06,2.06,0,0,1,.29-1,2.09,2.09,0,0,1,.86-.8,2.05,2.05,0,0,1,.49-.18l.23,0h.1a2.46,2.46,0,0,1,.54,0,2.36,2.36,0,0,1,.38.08,1,1,0,0,1,.39.13,5.88,5.88,0,0,0,1.15.45l.26.07.07,0,0,0,0,0,.74-.7c.54-.54,1.07-1.11,1.56-1.69l.69-.86s0,0,0,0v0h0l-.31-.14-.51-.21-.5-.2-.54-.25-.92-.46a21.42,21.42,0,0,1-2-1.14A5.35,5.35,0,0,1,66,49.45a4,4,0,0,1-.34-.5,1.87,1.87,0,0,1-.14-.27,2.32,2.32,0,0,1-.13-.37,1.74,1.74,0,0,1-.09-.51,3,3,0,0,1,0-.6,2.53,2.53,0,0,1,1.1-1.66,3,3,0,0,1,.79-.37,5.15,5.15,0,0,1,1.52-.2c.4,0,.76,0,1.11.06.7.06,1.37.14,2,.22a4.12,4.12,0,0,0,1.31.06,31,31,0,0,1,5.26.67h.05a1.29,1.29,0,0,0,.31-.13,7.07,7.07,0,0,0,.63-.41c.33-.22.81-.62,1.24-1l1.35-1.06a33.32,33.32,0,0,1,2.87-2,2.55,2.55,0,0,1,.91-.47A8,8,0,0,0,88,40.11a6.14,6.14,0,0,1,3.35-.55,2.76,2.76,0,0,1,1.58.91c.37.37-.17.62-.31.61-.45-.06-.25.32-.34.5a.86.86,0,0,1-.11.19.42.42,0,0,1-.19,0l-.18,0-.25,0a3.31,3.31,0,0,0-1.33.4,17.94,17.94,0,0,0-2.25,1.61s-.41.3-1,.74-1.3,1.08-2,1.77-1.47,1.44-2.09,2.08a10,10,0,0,1-1.76,1.44,4.36,4.36,0,0,1-2.3.63,4.09,4.09,0,0,1-1.11-.07c-.37-.06-1.79-.27-3.19-.42s-2.72-.26-2.83-.26c-.62,0-1.24,0-1.82,0H69a1.42,1.42,0,0,1-.31,0l-.09,0v0s0,.06,0-.1a4.61,4.61,0,0,0-.16-.64c0-.15-.09-.29-.13-.43a2.57,2.57,0,0,0-.16-.37.76.76,0,0,0-.15-.26c-.07-.08-.06-.11-.12-.15s-.08,0,0,0a.45.45,0,0,0,.19-.06l0,0h0l.52-.29h0l.09-.05a4.16,4.16,0,0,0,.79-.7s0,0,.09,0l.44.25c.37.19.83.39,1.35.6l.87.4.71.34.83.42.48.25c.24.13.45.27.68.41a5.26,5.26,0,0,1,2,2.15,3.19,3.19,0,0,1,.25,1.42,1.9,1.9,0,0,1-.14.7,3.33,3.33,0,0,1-.28.69,3.72,3.72,0,0,1-.65.91,6.17,6.17,0,0,1-.48.54l-.4.43A25.27,25.27,0,0,1,72,58.9l-.47.33c-.06.06-.22.13-.34.22l-.38.24A6.38,6.38,0,0,1,70,60a2.6,2.6,0,0,1-.88,0c-1.39-.22-1.86-.55-2.55-.64l-.22,0s-.08,0-.11,0l0,0h0l.07-.28a3.68,3.68,0,0,0,.18-1.5s0,0,0,0a.23.23,0,0,0,.1,0l.35-.18a4,4,0,0,0,.48-.35l.3-.24c.08-.08.22-.22.18-.17l0,0,.1.12c.17.18.44.41.71.65l.22.2a2.83,2.83,0,0,1,.3.3c.21.19.37.39.53.56a4.44,4.44,0,0,1,.39.65,2.84,2.84,0,0,1,.21.46A2.08,2.08,0,0,1,70,61.16,7,7,0,0,1,68.92,62.36Z"
/>
<path
className="cls-1"
d="M44.26,15.62a9.29,9.29,0,0,1,7.24-3c1.14.06,2.54-1.62.87-1.7a13,13,0,0,0-10.15,4c-1.08,1.07,1.3,1.39,2,.66Z"
/>
<path
className="cls-1"
d="M111.67,47.16a8.2,8.2,0,0,1,2.38,8.72c-.41,1.09,1.62,1.07,1.93.23a9.12,9.12,0,0,0-2.46-9.84c-.66-.63-2.57.21-1.85.89Z"
/>
<path
className="cls-1"
d="M116.62,43.57a5.66,5.66,0,0,1,2.79,5.3c0,.89,2,.51,2-.23a6.49,6.49,0,0,0-3.22-6.11c-.61-.39-2.46.47-1.61,1Z"
/>
<path
className="cls-1"
d="M41.44,40.62c.2,2.67-4.89,2.84-4.43-.3.31-2.2,3.72-2.34,4.34-.18A2.23,2.23,0,0,1,41.44,40.62Z"
/>
<path
className="cls-1"
d="M31.38,50.19c.12,1.59-2.93,1.7-2.66-.19a1.35,1.35,0,0,1,2.6-.1A1.5,1.5,0,0,1,31.38,50.19Z"
/>
<path
className="cls-1"
d="M80.78,98.68c.12,1.6-2.94,1.7-2.66-.19a1.35,1.35,0,0,1,2.6-.1A1.67,1.67,0,0,1,80.78,98.68Z"
/>
</g>
</svg>
);
};
export const GiftIcon = () => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 128 128"
className="w-14 fill-primary"
>
<title>Free Icons</title>
<g
id="Layer_14"
data-name="Layer 14"
>
<path
className="cls-1"
d="M16,103.87l-.26-5.22c0-.64-.14-1.27-.17-1.91-.11-2.24-.22-4.49-.37-6.74-.08-1-.19-2-.3-3a20.29,20.29,0,0,1-.28-3.82c0-.4.4-.38.81-.08a2.58,2.58,0,0,1,1,1.58c.21,1.28.42,2.55.58,3.84s.26,2.58.31,3.89c.05,1.57.38,3.17.57,4.77s.36,3.5.5,5.26l.25,3.26c.14,1.64.21,3.29.37,4.92.12,1.27.4,2.51.58,3.77a7.83,7.83,0,0,1,.1.83c0,1.05-.16,1.39-.87,1.61a4.42,4.42,0,0,1-.48.15c-.54.1-1-.32-1.21-1.06a33.15,33.15,0,0,1-.88-6.82c-.11-1.74-.21-3.49-.32-5.24Z"
/>
<path
className="cls-1"
d="M37.18,115.42c3.31.12,6.62.25,9.92.31h3.62c4.26.09,8.52.17,12.77.08,1.88,0,3.77-.14,5.63-.28,1.2-.09,2.39-.22,3.57-.35s2.39-.24,3.44-.47c.65-.12.81.24.33.85a3.91,3.91,0,0,1-.5.5,6.21,6.21,0,0,1-2.57,1.09c-2.49.43-5,.69-7.44.87s-5,.13-7.46.07c-3-.08-6.07.11-9.11.13-3.35,0-6.7,0-10-.07L33.17,118c-3.12-.07-6.24-.18-9.34-.22-2.41,0-4.78.08-7.18,0-.53,0-1-.05-1.58-.12-2-.24-2.58-.54-2.92-1.17a2.43,2.43,0,0,1-.22-.42c-.12-.45.72-.69,2.13-.76,4.21-.36,8.62-.18,13.11-.14l10,.21Z"
/>
<path
className="cls-1"
d="M82.85,88.56l.07,6.2c0,.75.1,1.5.11,2.26,0,2.66.06,5.32.14,8,0,1.18.14,2.36.26,3.52a30.63,30.63,0,0,1,.26,4.44.36.36,0,0,1-.09.23l-.09.07s0,0-.11,0l-.1,0,.06,0H83.1a1.1,1.1,0,0,1-.37-.17,3,3,0,0,1-1.17-1.94,39.64,39.64,0,0,1-.4-4.61c-.08-1.54-.1-3.08-.06-4.64,0-1.86-.19-3.78-.27-5.67L80.61,90l-.11-3.85c-.07-1.94-.1-3.9-.2-5.82-.09-1.5-.31-3-.45-4.46,0-.33-.08-.65-.08-1,0-1.23.2-1.65.78-1.89a2.05,2.05,0,0,1,.38-.16c.4-.1.8.4,1,1.27a52.47,52.47,0,0,1,.81,8.16c.1,2.08.11,4.17.18,6.25Z"
/>
<path
className="cls-1"
d="M99.38,99.27c1-.87,2-1.74,3-2.58.37-.36.2,0,.26-.9l0-2,0-2.85c0-3.35-.09-6.71-.19-10.07,0-1.5-.14-3-.24-4.47-.12-1.9-.29-3.81-.23-5.72,0-1.19,1.2.26,1.43,2.44.33,3.86.71,7.73.72,11.66,0,2.35.23,4.79.29,7.2,0,1.32,0,2.64,0,4v.56a6.71,6.71,0,0,1,0,.78l-1,.87L102,99.52c-1.2,1.08-2.4,2.18-3.58,3.28l-5.4,5c-1.39,1.3-2.7,2.65-4.1,3.92-.31.28-.6.58-.93.84a4.17,4.17,0,0,1-1.41.9,1.26,1.26,0,0,1-.92,0,2.61,2.61,0,0,1-.37-.14c-.31-.18,0-.89.73-1.7,2.39-2.28,5-4.62,7.55-7l5.81-5.37Z"
/>
<path
className="cls-1"
d="M97.45,66.7c1.6-.78,3.18-1.6,4.7-2.49.28-.17.54-.35.8-.53l.36-.25.22-.22a5.67,5.67,0,0,0,1.35-2.64,9.4,9.4,0,0,0,.26-3.22,7.6,7.6,0,0,0-.79-2.78,8.68,8.68,0,0,0-2.3-2.77c-.27-.26-.09-.52.37-.6a2.44,2.44,0,0,1,.9.07,2.87,2.87,0,0,1,1,.61,9.53,9.53,0,0,1,2.33,8.24,11.4,11.4,0,0,1-.72,2.59A5.29,5.29,0,0,1,104.18,65c-1.55,1-3.14,1.94-4.75,2.81-1,.53-2,1-3,1.55-1.51.76-3.07,1.47-4.58,2.22-1.18.57-2.28,1.24-3.45,1.84-.25.13-.49.27-.76.4-1,.43-1.35.42-1.77,0a2.61,2.61,0,0,1-.28-.31c-.26-.38,0-.88.67-1.29A62.35,62.35,0,0,1,92.59,69c1.61-.76,3.24-1.52,4.84-2.35Z"
/>
<path
className="cls-1"
d="M8.53,67.52a11,11,0,0,1,.88-3.32,7.44,7.44,0,0,1,2.19-2.92c.14-.1.22-.19.4-.3a5,5,0,0,1,.66-.32c.36-.11.64-.16,1-.23.56-.07,1.11-.13,1.63-.16,1.05-.07,2.07-.07,3.09-.07,4.07,0,8.07.24,12.08.43l8.76.41c10.28.55,20.57,1.15,30.83,1,2.27-.06,4.55-.17,6.8-.4.57,0,1.13-.12,1.69-.19.26,0,.59-.06.81-.11l.27-.09.36-.16c1-.45,2-1,3-1.54C88,56.71,93.1,53.71,98.69,51.74c1.78-.57,1.66,0,.39.92a50.28,50.28,0,0,1-6.54,4.08c-2.61,1.38-5.19,2.83-7.82,4.25-1.33.71-2.58,1.42-4.1,2.09a5,5,0,0,1-1.42.39l-1.14.13c-.75.09-1.51.14-2.27.21a162.26,162.26,0,0,1-18.05.13c-7.19-.29-14.67-.5-22-.85-4-.19-8.06-.39-12.09-.52-2-.07-4-.11-6-.09-1,0-2,.05-2.94.13L14,62.7c-.2,0-.43.09-.58.14a.26.26,0,0,1-.15,0,1.5,1.5,0,0,1-.23.2,3.12,3.12,0,0,0-.46.43c-1.44,1.56-1.91,4-1.78,6.33a13.3,13.3,0,0,0,.68,3.42,5.64,5.64,0,0,0,.31.81,5.5,5.5,0,0,0,.38.77,4.78,4.78,0,0,0,.44.72l.24.35a2.49,2.49,0,0,0,.23.23,5.76,5.76,0,0,0,2.2,1A22.52,22.52,0,0,0,18,77.7c1.82.27,3.68.4,5.55.49,3.73.17,7.48.15,11.2.06,5.8-.14,11.47-.59,17.21-.85,1.27-.06,2.51-.14,3.78-.18,4.74-.13,6.27.07,7.28.74a5,5,0,0,1,.66.46c.44.53-1.48.9-4.91,1.11-10.21.65-21,1.37-32,1.22-2,0-4.09-.12-6.16-.29a32.23,32.23,0,0,1-6.32-1.06l-.83-.29c-.29-.11-.58-.26-.86-.39s-.6-.37-.89-.56l-.45-.43a2.91,2.91,0,0,1-.36-.42A11.59,11.59,0,0,1,9.25,74.2a15.41,15.41,0,0,1-.78-6.67Z"
/>
<path
className="cls-1"
d="M23.93,55.79c1.19-.26,2.38-.55,3.56-.88.43-.13.84-.3,1.27-.43l4.59-1.34c.67-.2,1.34-.45,2-.7a9.16,9.16,0,0,1,2.59-.79c.29,0,.34.23.23.59a2.18,2.18,0,0,1-.85,1.14,30.82,30.82,0,0,1-5.16,2c-1.09.27-2.14.77-3.22,1.14s-2.4.76-3.61,1.11l-2.25.59c-1.13.29-2.29.52-3.41.82-.87.24-1.7.56-2.57.78-.19,0-.37.11-.57.15-.72.13-1,0-1.22-.38a2.09,2.09,0,0,1-.17-.28c-.13-.33.1-.69.59-.94a18.77,18.77,0,0,1,4.61-1.7l3.57-.89Z"
/>
<path
className="cls-1"
d="M83.9,47.55l3.07.37c.37,0,.75,0,1.12.07l4,.51c.58.07,1.17.09,1.75.11a7.1,7.1,0,0,1,2.24.24c.23.08.2.33,0,.61a1.64,1.64,0,0,1-1,.7A20.69,20.69,0,0,1,90.44,50a22,22,0,0,0-2.82-.16l-3.1-.23-1.91-.14c-1-.07-1.93-.16-2.89-.17-.75,0-1.48.1-2.22.1-.16,0-.32,0-.48,0-.61,0-.79-.18-.91-.63,0-.1-.06-.2-.07-.3-.05-.34.21-.62.66-.74a11.56,11.56,0,0,1,4.1-.46c1,0,2.07.12,3.1.22Z"
/>
<path
className="cls-1"
d="M29.93,80.41c2.52,0,5.06,0,7.59-.07l2.78-.15c3.26-.11,6.54-.2,9.81-.35,1.45-.07,2.91-.17,4.35-.27A51.74,51.74,0,0,1,60,79.39c.58,0,.5.27,0,.53a6.79,6.79,0,0,1-2.42.64c-3.75.3-7.5.68-11.31.85-2.28.09-4.64.39-7,.52-2.57.15-5.14.26-7.72.3-1.58,0-3.17,0-4.76,0a58.51,58.51,0,0,1-7.23-.56,27.49,27.49,0,0,1-2.79-.55,7.75,7.75,0,0,1-2.76-1.22,3.64,3.64,0,0,1-.56-.48L13.12,79A6.48,6.48,0,0,1,12,77.89a.89.89,0,0,1,0-1.14.87.87,0,0,1,.35-.27c.22-.07.41.07.59.13a1.94,1.94,0,0,1,.79.3,4.62,4.62,0,0,1,1.19.93,4.36,4.36,0,0,0,.73.55,8,8,0,0,0,2,.79,27.77,27.77,0,0,0,4.76.83c2.47.24,5,.34,7.56.35Z"
/>
<path
className="cls-1"
d="M98.32,69.93c-.68.33-1.39.6-2.08.89-.25.09-.49.23-.75.32l-2.7.92a11.84,11.84,0,0,0-1.17.46,7.38,7.38,0,0,1-1.49.56c-.33.08-.28-.83.24-1.17a12.88,12.88,0,0,1,3-1.33,12.79,12.79,0,0,0,1.82-.81c.66-.3,1.31-.61,2-.94.39-.2.79-.4,1.18-.63a15.84,15.84,0,0,0,1.7-1.09c.43-.3.77-.71,1.17-1l.25-.22c.35-.25.52-.25.8-.06l.19.14c.19.16.18.44,0,.73a5.42,5.42,0,0,1-.94,1.19,6.87,6.87,0,0,1-1.18,1,20.42,20.42,0,0,1-2,1.15Z"
/>
<path
className="cls-1"
d="M47.11,100.09,47,95.78c0-.53-.09-1-.1-1.57,0-1.86,0-3.72,0-5.59V86.14a8.47,8.47,0,0,1,.38-3.24c.13-.34.43-.17.72.17a2.52,2.52,0,0,1,.62,1.38c0,1,.13,2,.2,3.08s0,2.1,0,3.17a32.28,32.28,0,0,0,.29,3.9l.29,4.32.19,2.66c.1,1.35.17,2.7.34,4,.12,1,.41,2,.56,3.08a6.86,6.86,0,0,1,.12.68c.08.86-.14,1.15-.76,1.35-.14,0-.26.1-.38.12A1.1,1.1,0,0,1,48.3,110a23.77,23.77,0,0,1-.95-5.58c-.12-1.44-.19-2.88-.3-4.33Z"
/>
<path
className="cls-1"
d="M53.42,95.49q-4.05,0-8.09.11c-1,0-2,.12-2.95.14-3.47.08-6.94.16-10.41.34-1.54.09-3.08.23-4.59.4-1.94.22-3.92.56-5.79.64-.56,0-.64-.34-.22-.86a3.47,3.47,0,0,1,1-.79,3.92,3.92,0,0,1,1.51-.53A99.77,99.77,0,0,1,36,94c2.43,0,4.94-.3,7.42-.42q4.08-.17,8.18-.25l5-.08,7.62-.07c2,0,3.89-.19,5.84-.25.43,0,.85,0,1.28,0,1.61,0,2.12.22,2.43.83a2.67,2.67,0,0,1,.2.42c.12.46-.55.82-1.71.91-1.71.13-3.48.26-5.27.27s-3.6,0-5.43.08c-2.7,0-5.43,0-8.15.09Z"
/>
<path
className="cls-1"
d="M97.08,83.65v4c0,.49.06,1,.06,1.45,0,1.71-.05,3.42,0,5.13,0,.76,0,1.52.09,2.27a19,19,0,0,1,0,2.92c-.07.6-.9-.15-1.12-1.23a24.16,24.16,0,0,1-.53-5.89c0-1.19-.17-2.41-.24-3.63s-.11-2.67-.15-4l-.07-2.47c0-1.25,0-2.51-.13-3.75-.06-1-.22-1.9-.31-2.87a4.64,4.64,0,0,1,0-.64c0-.81.28-1.07.74-1.2l.29-.09a.51.51,0,0,1,.45.2,1.4,1.4,0,0,1,.36.65A12,12,0,0,1,96.89,77c.1.87.13,1.75.16,2.64,0,1.33,0,2.67.08,4Z"
/>
<path
className="cls-1"
d="M93,88c.74-.48,1.48-1,2.19-1.53.26-.2.48-.44.74-.64l2.75-2.18c.4-.33.79-.68,1.17-1a8.61,8.61,0,0,1,1.56-1.26c.36-.22.47.74,0,1.29a28.55,28.55,0,0,1-2.88,2.83c-.66.49-1.22,1.13-1.85,1.69s-1.43,1.2-2.18,1.76q-.69.51-1.41,1c-.73.49-1.51.9-2.27,1.34-.6.32-1.16.72-1.79,1a1.4,1.4,0,0,1-.42.18.89.89,0,0,1-.64,0,.87.87,0,0,1-.35-.36,1.73,1.73,0,0,1-.13-.21c-.1-.23.06-.55.35-.88a21.06,21.06,0,0,1,2.93-1.66A26.1,26.1,0,0,0,93,87.91Z"
/>
<path
className="cls-1"
d="M104,87.83s11.84-.09,13.85,5.36c2.43,6.56-15.26,16.41-31.12,19.14L103.66,97Z"
/>
<path
className="cls-1"
d="M62.4,24.22A1.25,1.25,0,0,1,64,23.4C67.25,24.41,61.33,27.67,62.4,24.22Z"
/>
<path
className="cls-2"
d="M50.21,11.76a1.24,1.24,0,0,1,1.57-.82C55.06,12,49.14,15.21,50.21,11.76Z"
/>
<path
className="cls-2"
d="M26.22,31.38a1.25,1.25,0,0,1,1.57-.82C31.07,31.57,25.15,34.83,26.22,31.38Z"
/>
<path
className="cls-2"
d="M93.25,24.22a1.25,1.25,0,0,1,1.57-.82C98.1,24.41,92.18,27.67,93.25,24.22Z"
/>
<path
className="cls-3"
d="M38.24,48.36a12.66,12.66,0,0,1-.91-4.4,6.71,6.71,0,0,1,1.6-4.67,6.3,6.3,0,0,1,3.14-1.9,7,7,0,0,1,3.12,0,9.92,9.92,0,0,1,2.65,1.09A18.08,18.08,0,0,1,52,42a39.52,39.52,0,0,1,2.95,3.54,12.46,12.46,0,0,1,2.66,5.34c.09.67-.65.71-1.46.46a3.62,3.62,0,0,1-2.18-1.61,28.08,28.08,0,0,0-6.56-8.29,6.31,6.31,0,0,0-2.7-1.32,4.1,4.1,0,0,0-2.63.29,3.09,3.09,0,0,0-1.78,2.09,7.25,7.25,0,0,0,.08,3.33,10.2,10.2,0,0,0,1.9,3.95,16,16,0,0,0,5.35,4.36,23.83,23.83,0,0,0,5.1,1.81l1.16.28c1.43.39,1.84.67,2,1.49a3.78,3.78,0,0,1,.08.56c0,.59-.73.92-1.88.77a23.58,23.58,0,0,1-10.14-3.91,15.76,15.76,0,0,1-5.69-6.69Z"
/>
<path
className="cls-3"
d="M73.11,42.22a9.19,9.19,0,0,0,.68-3.93,1.52,1.52,0,0,0-.45-1A2,2,0,0,0,72,37a4.89,4.89,0,0,0-1.41.33l-.7.24-.7.34a17.84,17.84,0,0,0-4.64,3.37,30.46,30.46,0,0,0-3.86,4.59,27.61,27.61,0,0,0-2.61,4.69c-.93,2.09-1.54,4.28-2.33,6.38-.25.65-1,.45-1.5-.32a4,4,0,0,1-.46-3.51,33.29,33.29,0,0,1,7.89-12.72,44.85,44.85,0,0,1,3.44-3.11,14.16,14.16,0,0,1,4.18-2.45,9.09,9.09,0,0,1,2.75-.57,4,4,0,0,1,4.47,3.91,9.49,9.49,0,0,1-.18,2.74A19.38,19.38,0,0,1,74,46.78a22.94,22.94,0,0,1-6.37,6.88c-1.94,1.43-3.91,2.69-5.83,3.93l-1.25.83c-1.58,1-2.15,1.17-2.91.76a3.53,3.53,0,0,1-.51-.28c-.48-.37-.11-1.23,1-2.13,3.36-2.69,7.31-4.48,10.1-7.23a20.43,20.43,0,0,0,2.8-3.4,16.47,16.47,0,0,0,2-3.94Z"
/>
</g>
</svg>
);
};
export const LightBulbIcon = () => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 128 128"
className="w-12 fill-primary"
>
<title>Free Icons</title>
<g
id="Layer_49"
data-name="Layer 49"
>
<path
className="cls-1"
d="M62,109a23.62,23.62,0,0,1-5.73-.76,13.32,13.32,0,0,1-2.07-.71A9.7,9.7,0,0,1,51,105.18a9.6,9.6,0,0,1-1.13-1.6,5.1,5.1,0,0,1-.63-2,4.81,4.81,0,0,1,.13-1.85,5.67,5.67,0,0,1,.8-1.66,4.54,4.54,0,0,1,3.94-1.88c.46,0,.39.26.1.62a10.79,10.79,0,0,1-1.2,1.32,5.51,5.51,0,0,0-1,1.12,2.9,2.9,0,0,0-.51,1.22,2.83,2.83,0,0,0-.05,1.33,4.84,4.84,0,0,0,.64,1.48,5.59,5.59,0,0,0,1.51,1.56,11,11,0,0,0,2,1,16.87,16.87,0,0,0,5.12,1,28.47,28.47,0,0,0,3.33,0,21.14,21.14,0,0,0,5-.8,16.56,16.56,0,0,0,3.48-1.48c.25-.13.47-.28.71-.42.89-.52,1.22-.62,1.62-.47a2.14,2.14,0,0,1,.27.09c.22.11.06.62-.56,1.2a14.07,14.07,0,0,1-3.13,2.2,16,16,0,0,1-1.79.8c-.63.2-1.27.36-1.91.5a27.47,27.47,0,0,1-5.77.52Z"
/>
<path
className="cls-1"
d="M67.12,109.72a30,30,0,0,1-3.11.63l-1.15.15a19.19,19.19,0,0,1-4.08-.12c-.6-.08-1.2-.18-1.79-.31a5.83,5.83,0,0,1-2.17-.87c-.2-.15,0-.33.25-.44a1.56,1.56,0,0,1,1,0,16.18,16.18,0,0,0,4.28.85,12.74,12.74,0,0,0,2.75-.16,24.16,24.16,0,0,0,3-.57c.61-.15,1.21-.35,1.81-.54l1.36-.48,1.31-.56c.67-.33,1.28-.72,1.93-1.07L73,106c.53-.29.74-.31,1-.22l.14.06c.12.08,0,.31-.38.62a13.85,13.85,0,0,1-3.55,2.23,18.67,18.67,0,0,1-3,1.1Z"
/>
<path
className="cls-1"
d="M69.12,116.17a4.5,4.5,0,0,0,.86-1.08c.1-.15.13-.34.22-.49a18,18,0,0,0,.87-1.82c.13-.27.23-.57.34-.86a2,2,0,0,1,.66-1.1c.12-.1.25.09.38.32s.27.44.23.63a7.41,7.41,0,0,1-.71,2.15c-.25.42-.35.93-.57,1.4a8.7,8.7,0,0,1-.88,1.49,5.23,5.23,0,0,1-.78.78l-.32.27-.38.2a3.72,3.72,0,0,1-.77.33,3.42,3.42,0,0,1-.61.22,4.64,4.64,0,0,1-.64.17,1.31,1.31,0,0,1-.28,0c-.35,0-.45-.15-.48-.5,0-.08,0-.15,0-.22a.72.72,0,0,1,.36-.58c.63-.31,1.09-.41,1.54-.63a3.77,3.77,0,0,0,.94-.7Z"
/>
<path
className="cls-1"
d="M53.37,98.52a3.31,3.31,0,0,0-.81.42c-.09.07-.14.17-.24.25a4.46,4.46,0,0,0-.91.93,1,1,0,0,0-.13.52c0,.23.08.36-.1.54a2.13,2.13,0,0,1-.88.29c-.41.07-1-.13-1-.41a2.07,2.07,0,0,1,.13-1.28,2.6,2.6,0,0,1,.65-.93c.33-.3.48-.7.77-1A5.77,5.77,0,0,1,51.93,97a5.23,5.23,0,0,1,.79-.38c.2-.09.44-.13.65-.2s.46-.07.69-.09.37-.05.56-.05a2.84,2.84,0,0,1,.58.05.4.4,0,0,1,.23.1c.25.19.26.37.08.73a1.71,1.71,0,0,1-.13.23,1.54,1.54,0,0,1-.56.53c-.56.31-.59.4-.82.46a2.36,2.36,0,0,0-.6.22Z"
/>
<path
className="cls-1"
d="M36.22,81.71a49.21,49.21,0,0,1-6.29-9c-.33-.59-.62-1.2-.9-1.81a17.8,17.8,0,0,1-.8-1.85,31.33,31.33,0,0,1-2.14-13.93c.06-1,.23-2.09.36-3.13s.35-2.06.64-3.06a20.29,20.29,0,0,1,3.16-7.33c.49-.68.53-.51.29.16S29.88,43.6,29.33,45c-.25.61-.46,1.23-.65,1.86s-.33,1.28-.52,1.92a18,18,0,0,0-.45,1.93c-.12.65-.29,1.29-.36,2a31.09,31.09,0,0,0-.19,8A28.89,28.89,0,0,0,29.84,70a44.29,44.29,0,0,0,5.7,9.21,58.71,58.71,0,0,0,4.43,5,99.8,99.8,0,0,0,7.48,6.92c2,1.7,4,3.27,6.07,4.91.44.37.89.71,1.32,1.1,1.62,1.42,2,2,2.21,2.47a2.21,2.21,0,0,1,.12.32c0,.25-.7-.25-1.91-1.23-3.6-2.88-7.51-5.87-11.22-9.15a82.77,82.77,0,0,1-7.84-7.83Z"
/>
<path
className="cls-1"
d="M31.45,39.67a31.31,31.31,0,0,1,5.45-5.58,36.26,36.26,0,0,1,6.63-4A33.3,33.3,0,0,1,64.1,27.69c.91.18,1.83.4,2.73.67s1.79.64,2.68,1a22.87,22.87,0,0,1,8,5.93,27.22,27.22,0,0,1,5,8.49A39.66,39.66,0,0,1,84.41,63a59.78,59.78,0,0,1-1.69,8.4A77.05,77.05,0,0,1,80,79.42a80,80,0,0,1-4.59,9.85,79.92,79.92,0,0,1-5.8,9.16c-1.33,1.82-1.39,1.39-.64-.38.38-.88.93-2.12,1.62-3.59s1.5-3.18,2.45-5c1.69-3.21,3.14-6.53,4.52-9.86A76.26,76.26,0,0,0,81,69.37a44.2,44.2,0,0,0,.63-21.22,30.27,30.27,0,0,0-2.18-6.06,23.37,23.37,0,0,0-3.62-5.34,19.76,19.76,0,0,0-5-4.06,23.39,23.39,0,0,0-6-2.34,31.52,31.52,0,0,0-27.15,6.22A24.28,24.28,0,0,0,32,43.27c-.33.66-.68,1.31-1,2l-.76,2.07a34.32,34.32,0,0,0-1,4.36l-.14.83-.07.85-.13,1.69v2.54l.08.84a29.74,29.74,0,0,0,1.3,6.66,37.55,37.55,0,0,0,2.63,6.28,52.37,52.37,0,0,0,3.63,5.78c4.18,5.72,9.32,10.48,14.6,15.14,1.16,1,2.32,2,3.48,3.08,4.32,3.91,5.49,5.63,5.71,7a3.87,3.87,0,0,1,.08.89c0,.16-.12.15-.29,0s-.36-.41-.73-.77c-.69-.71-1.83-1.83-3.41-3.22-4.74-4.07-9.84-8.2-14.5-13A58.44,58.44,0,0,1,29.61,69.75a37.92,37.92,0,0,1-2.42-7.4,32,32,0,0,1-.62-7.82,33.6,33.6,0,0,1,1.3-7.73,25.94,25.94,0,0,1,3.52-7.16Z"
/>
<path
className="cls-1"
d="M57.3,107.39a23.41,23.41,0,0,0,7.92,0c1-.17,1.94-.44,2.87-.64a19,19,0,0,0,4.64-2,12.83,12.83,0,0,0,3.76-3.28,3.43,3.43,0,0,0,.28-3.76,6,6,0,0,0-2-1.84,15.3,15.3,0,0,0-2.61-1.25c-.57-.19-.49-.38.1-.54a4.65,4.65,0,0,1,2.94.22,7.54,7.54,0,0,1,2.9,2.11,5.67,5.67,0,0,1,.94,1.79,4.41,4.41,0,0,1,.07,2.08,7.14,7.14,0,0,1-1.73,3.32,11.69,11.69,0,0,1-2.6,2.19,31.12,31.12,0,0,1-3.48,2,19.59,19.59,0,0,1-1.88.79c-.31.12-.66.21-1,.31l-1,.21a29,29,0,0,1-8.63.71,19.64,19.64,0,0,1-5.27-1.19A12.61,12.61,0,0,1,50,106.36a7.81,7.81,0,0,1-2.32-3.53,5.91,5.91,0,0,1,0-3.41,6.7,6.7,0,0,1,1.94-2.78,9,9,0,0,1,1.18-.87,4.55,4.55,0,0,1,1.79-.65,1.23,1.23,0,0,1,.94.27,1.34,1.34,0,0,1,.31.26c.24.32-.32.79-1.25,1.38a6,6,0,0,0-2.85,3.28,3.6,3.6,0,0,0,0,1.9,5.63,5.63,0,0,0,1,1.88,11,11,0,0,0,6.51,3.25Z"
/>
<path
className="cls-1"
d="M54.63,102.66a17.26,17.26,0,0,0,4.6,1.17c.59.07,1.18.06,1.77.08a21.85,21.85,0,0,0,6.29-.58,13.07,13.07,0,0,0,2.62-1,11.85,11.85,0,0,0,2.77-2c.26-.24.45-.1.49.33a2.16,2.16,0,0,1-.72,1.75,13,13,0,0,1-7.37,3,37.89,37.89,0,0,1-4.79.34,18.87,18.87,0,0,1-5.25-.83,12.92,12.92,0,0,1-3-1.4,8.26,8.26,0,0,1-1.92-1.72,7.11,7.11,0,0,1-.71-1.1A2.85,2.85,0,0,1,49,99.23a3.87,3.87,0,0,1,.69-2.06,5.75,5.75,0,0,1,1.44-1.47,4.81,4.81,0,0,1,.78-.48c1.07-.48,1.56-.29,1.8.13a1.34,1.34,0,0,1,.15.29c.08.32-.27.62-.78.9a5,5,0,0,0-1.93,1.79,1.7,1.7,0,0,0-.27.91.8.8,0,0,0,.09.3c0,.11.2.35.29.53a7.08,7.08,0,0,0,3.37,2.54Z"
/>
<path
className="cls-1"
d="M60.39,111.81a13.18,13.18,0,0,0,4.18.23,13.75,13.75,0,0,0,1.56-.27,22.55,22.55,0,0,0,5.42-1.64,12.09,12.09,0,0,0,2.16-1.29,18.65,18.65,0,0,0,2.3-2.12c.24-.22.45-.09.56.33a1.92,1.92,0,0,1,0,.81,2.68,2.68,0,0,1-.44.9,13.29,13.29,0,0,1-6,3.88,38.18,38.18,0,0,1-4.19,1.22,17.44,17.44,0,0,1-4.84.23,13.45,13.45,0,0,1-3-.68A11.5,11.5,0,0,1,54.26,111,10.73,10.73,0,0,1,52,108.27c-.12-.24-.24-.47-.34-.71-.29-1-.12-1.31.28-1.6a2.14,2.14,0,0,1,.26-.19c.28-.15.7.14,1.07.65.54.76,1,1.48,1.55,2.14a8.56,8.56,0,0,0,1.89,1.71,10.4,10.4,0,0,0,3.67,1.49Z"
/>
<path
className="cls-1"
d="M71.89,116a8.26,8.26,0,0,1-2,2.11,4.18,4.18,0,0,1-1,.57,3.78,3.78,0,0,1-2,.23,5.32,5.32,0,0,1-1.76-.61c-.46-.25-.91-.5-1.34-.78-.27-.18-.55-.36-.8-.56a3.51,3.51,0,0,1-.61-.77c-.11-.18.08-.33.39-.42a1.71,1.71,0,0,1,1,0,14.14,14.14,0,0,0,2.91,1.62,2.06,2.06,0,0,0,1.75-.26,5.27,5.27,0,0,0,1.63-1.54,12.8,12.8,0,0,0,.81-1.29c.37-.69.75-1.4,1.07-2.14.25-.57.42-1.18.69-1.77.06-.13.11-.26.18-.39.29-.45.53-.5.95-.33.09,0,.18.06.25.1a.82.82,0,0,1,.34.86,13.34,13.34,0,0,1-1.19,3.06c-.39.76-.82,1.55-1.32,2.34Z"
/>
<path
className="cls-1"
d="M54.88,50.43a11.27,11.27,0,0,1,0-1.54l.06-.81L55,47.5c.06-.22.14-.42.2-.63a2.28,2.28,0,0,1,1.7-1.54,2.59,2.59,0,0,1,2.21.68,4.89,4.89,0,0,1,.44.47,2.59,2.59,0,0,1,.32.44,6.82,6.82,0,0,1,.41.74,10.84,10.84,0,0,1,.58,1.44,15.9,15.9,0,0,1,.69,3,20.62,20.62,0,0,1-1.84,11.56,14.49,14.49,0,0,1-1.11,1.9,10.25,10.25,0,0,1-.73.93,8.06,8.06,0,0,1-.93.81,5.94,5.94,0,0,1-4.7.9,11.15,11.15,0,0,1-3.64-1.53,15.38,15.38,0,0,1-2.95-2.44A14,14,0,0,1,43.48,61a13.19,13.19,0,0,1-1.3-3.61,6.59,6.59,0,0,1,.34-4,4.84,4.84,0,0,1,1.3-1.71A3.3,3.3,0,0,1,46,51a5.56,5.56,0,0,1,3.61,1.84,16,16,0,0,1,2.33,3c2.33,3.73,3.64,7.92,4.87,11.94a61,61,0,0,1,2,8A30,30,0,0,1,59,83.93c-.2,1.71-.46,1.44-.72,0L57.73,81c-.26-1.19-.53-2.57-.78-4.06a61.71,61.71,0,0,0-2-7.86c-.79-2.64-1.57-5.26-2.53-7.76a22.33,22.33,0,0,0-3.8-6.84,7.79,7.79,0,0,0-1.32-1.22,2.66,2.66,0,0,0-1.36-.49,1.49,1.49,0,0,0-1.12.48,3.31,3.31,0,0,0-.8,1.34,6.73,6.73,0,0,0,.5,4.3,13,13,0,0,0,2.53,4,13.34,13.34,0,0,0,3.89,2.76,5.33,5.33,0,0,0,4.21.33,4.41,4.41,0,0,0,1.74-1.46,14.17,14.17,0,0,0,1.28-2.29,18.2,18.2,0,0,0,1.36-5.16,18,18,0,0,0-.15-5.34,15,15,0,0,0-.74-2.53,7.69,7.69,0,0,0-.57-1.11,1.15,1.15,0,0,0-.47-.5.46.46,0,0,0-.64.26,1.3,1.3,0,0,0-.11.37,4,4,0,0,0-.11.75A14.08,14.08,0,0,0,57,52.26a16.47,16.47,0,0,0,.93,3.19A5.91,5.91,0,0,0,59.63,58a2.81,2.81,0,0,0,2,.41,4.5,4.5,0,0,0,2-1,8.69,8.69,0,0,0,2.66-4,5.47,5.47,0,0,0,.14-2.32,3.32,3.32,0,0,0-.85-1.92,1,1,0,0,0-1.45.09,5.81,5.81,0,0,0-1.23,2A9.82,9.82,0,0,0,62.4,53,17.79,17.79,0,0,0,62,55a31.91,31.91,0,0,0-.34,3.9,39.91,39.91,0,0,0,.59,7.8c.21,1.13.45,2.23.74,3.35.51,2.09,1,3.43,1.2,4.4a5.33,5.33,0,0,1,.22,2.1,5.43,5.43,0,0,1-.1.72c-.16.55-1.4-.9-2.51-4a40,40,0,0,1-2.19-14.83,36.34,36.34,0,0,1,.4-3.86c.12-.64.2-1.3.35-1.94l.21-1c.1-.37.21-.7.33-1a10,10,0,0,1,1-2,4.22,4.22,0,0,1,2.29-1.84,2.83,2.83,0,0,1,1.84.12,3.2,3.2,0,0,1,1.38,1,5.2,5.2,0,0,1,1.13,2.4,7.88,7.88,0,0,1-.05,3.48,10.15,10.15,0,0,1-1.4,3,10.67,10.67,0,0,1-2.22,2.39,6.26,6.26,0,0,1-3.31,1.36,5.35,5.35,0,0,1-1,0c-.33-.05-.64-.15-1-.23s-.58-.26-.86-.4a4.66,4.66,0,0,1-.83-.64,8.68,8.68,0,0,1-1.73-2.83,20,20,0,0,1-1.37-5.87Z"
/>
<path
className="cls-1"
d="M94.5,52.85c0,.17-.26.1-.62-.11a1.5,1.5,0,0,1-.39-.42,1.71,1.71,0,0,1,0-.38,11.77,11.77,0,0,1,.62-1,2.41,2.41,0,0,1,.56-.63,11.71,11.71,0,0,1,1.36-1,1.14,1.14,0,0,1,.36-.15,4.31,4.31,0,0,0,1.2-.53c.07,0,.14-.06.18-.16a3.35,3.35,0,0,1,1.36-.6,9.8,9.8,0,0,1,1.22,0c.06,0,.11,0,.18,0a.33.33,0,0,0,.37.13,1.73,1.73,0,0,1,.5.07,1,1,0,0,1,.25.22.66.66,0,0,1,0,.41c-.06.1,0,.23,0,.36a.57.57,0,0,1,0,.13,6.13,6.13,0,0,1-.8.71s-.28.11-.55.21a4,4,0,0,0-.61.29c-.06,0-.14,0-.21,0s-.81.46-.84.48c-.18.06-.31.2-.56.13,0,0-.08,0-.11,0a6.56,6.56,0,0,1-.89.41,2.44,2.44,0,0,0-.43.28l-.1,0a.35.35,0,0,0-.11,0,5.82,5.82,0,0,0-1,.72c-.06.06-.53.21-.6.3S94.5,52.78,94.5,52.85Z"
/>
<path
className="cls-1"
d="M84.86,30.57c0,.18-.27.1-.64-.12a1.48,1.48,0,0,1-.41-.43,1.94,1.94,0,0,1,0-.4c0-.07.43-.84.58-1.12a2.69,2.69,0,0,1,.53-.7c.42-.4.86-.77,1.3-1.13a.91.91,0,0,1,.34-.17,2.78,2.78,0,0,0,1.09-.65c.06-.05.12-.08.13-.18s.91-.84,1.05-.87c.37-.08.71-.21,1.06-.32.06,0,.08-.07.18,0s.29,0,.39,0a2,2,0,0,1,.45-.16,1,1,0,0,1,.35.08c.11,0,.29.31.3.35s.15.22.24.32l.1.11a4.6,4.6,0,0,1-.37,1.2s-1,.94-1.11,1.06-.15.07-.24.08-.81.75-.85.76c-.19.1-.32.29-.61.24-.06,0-.09,0-.12.05a5.22,5.22,0,0,1-1,.53c-.16.09-.29.22-.44.32a.38.38,0,0,1-.1,0,.33.33,0,0,0-.13,0,9.42,9.42,0,0,0-1,.76,6.13,6.13,0,0,0-.64.3S84.87,30.49,84.86,30.57Z"
/>
<path
className="cls-1"
d="M58.4,19.23c.11.16-.11.3-.5.43a1.33,1.33,0,0,1-.56,0,2.12,2.12,0,0,1-.31-.26c-.05-.05-.35-.9-.5-1.17a3.71,3.71,0,0,1-.26-.82c-.12-.56-.29-1.1-.39-1.65a1.21,1.21,0,0,1,0-.38,2.52,2.52,0,0,0-.13-1.28c0-.07,0-.15-.13-.2a2.76,2.76,0,0,1-.38-1.39,8.58,8.58,0,0,0,.19-1.22c0-.06,0-.11,0-.18s.13-.27.14-.4a2,2,0,0,1,.08-.53c.06-.1.18-.22.25-.32a.42.42,0,0,1,.31-.09c.1.06.19,0,.28-.06l.1,0a3.65,3.65,0,0,1,1.09.85s.15.34.31.7a7.8,7.8,0,0,0,.37.8c.05.08,0,.18,0,.27s.39,1.14.39,1.19c0,.24.13.47,0,.74a.16.16,0,0,0,0,.15,6.51,6.51,0,0,1,.05,1.25c0,.22,0,.42,0,.64a.84.84,0,0,1,0,.12,1,1,0,0,0,0,.14c0,.5-.06,1,0,1.5,0,.12-.2.67-.17.8S58.35,19.17,58.4,19.23Z"
/>
<path
className="cls-1"
d="M26,21c-.21,0-.1-.32.21-.74a2.42,2.42,0,0,1,.56-.46l.44-.06c.07,0,.8.4,1.08.48a2.35,2.35,0,0,1,.67.39l1.28.9a.78.78,0,0,1,.25.26,2.21,2.21,0,0,0,1,.78c.07,0,.12.08.22.05a3.43,3.43,0,0,1,1.25.66,11.21,11.21,0,0,0,.77.91s.11,0,.1.16.1.28.19.36a1.55,1.55,0,0,1,.35.37,1.09,1.09,0,0,1,.07.36c0,.12-.21.4-.25.42s-.15.23-.22.36a.57.57,0,0,1-.08.13,4.23,4.23,0,0,1-1.24.07L32,26.11c-.34-.14-.7-.28-.78-.3s-.13-.11-.18-.18-1.09-.43-1.13-.47-.43-.19-.52-.5c0-.05-.06-.07-.1-.09a5.07,5.07,0,0,1-1-.77,6.13,6.13,0,0,0-.51-.38s0-.07-.07-.1a.29.29,0,0,0-.08-.13c-.4-.31-.7-.73-1.12-1-.11-.06-.32-.64-.43-.72S26.1,21,26,21Z"
/>
</g>
</svg>
);
};
export const WalletIcon = () => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 128 128"
className="w-12 fill-primary"
>
<title>Free Icons</title>
<g
id="Layer_21"
data-name="Layer 21"
>
<path
className="cls-1"
d="M59.87,118c-4,.68-8.08,1.46-12.24,1.85A36.91,36.91,0,0,1,35,119.22a16.72,16.72,0,0,1-8.31-4.74,17.79,17.79,0,0,1-3.9-7.45,77.46,77.46,0,0,1-1.46-7.9c-.72-5.26-1.09-10.52-1.55-15.75a136.6,136.6,0,0,0-1.81-13.8c-.53-2.91-1.13-5.81-1.88-8.66-.19-.71-.38-1.42-.59-2.13s-.37-1.42-.55-2.13c-.42-1.41-.87-2.81-1.38-4.2-.7-1.69-.56-1.52.44-.25a25.18,25.18,0,0,1,3.87,7.09,91,91,0,0,1,2.26,9c.57,3,1,6.06,1.37,9.11.71,6.1,1,12.19,1.68,18.22a71.88,71.88,0,0,0,1.93,10.8,17.49,17.49,0,0,0,2.17,4.77,13.34,13.34,0,0,0,3.63,3.63c3.17,2.1,7.2,2.81,11.19,2.86a69.24,69.24,0,0,0,12.11-1.16l7.48-1.29c2.47-.46,4.94-1,7.39-1.59,3.71-.91,7.41-1.93,11-3.09a80.37,80.37,0,0,0,10.59-4.11,28.19,28.19,0,0,0,3.72-2.15,8,8,0,0,0,2.68-2.76A15.26,15.26,0,0,0,98,97.57a26.4,26.4,0,0,0,.13-4.18c-.07-1.23-.21-2.44-.38-3.68-.65-4.59-1.14-5.95-.49-7.24a6.47,6.47,0,0,1,.28-.82c.23-.61,1.91,1,2.77,4.58a38.31,38.31,0,0,1,.78,4.06,34.2,34.2,0,0,1,.25,4.2,29,29,0,0,1-.39,4.32l-.23,1.09-.3,1.1a10.39,10.39,0,0,1-1,2.35,12.42,12.42,0,0,1-3.57,3.32,33.67,33.67,0,0,1-3.83,2.13,73.9,73.9,0,0,1-7.91,3.14c-4,1.34-8,2.45-12,3.45s-8.11,2-12.23,2.66Z"
/>
<path
className="cls-1"
d="M87.47,31.43a12.15,12.15,0,0,0-4.86-.13,46.31,46.31,0,0,0-5.13,1.28c-3.45,1-6.88,2.23-10.3,3.44L59.7,38.76c-4.41,1.56-8.84,3.1-13.32,4.53A141.12,141.12,0,0,1,32.76,47a61.74,61.74,0,0,1-6.23,1,23.19,23.19,0,0,1-6.39,0l-1-.21c-.34-.09-.68-.22-1-.33a5.19,5.19,0,0,1-1-.46c-.16-.09-.32-.17-.48-.27a3.56,3.56,0,0,1-.48-.39,3.06,3.06,0,0,1-.75-1A3.26,3.26,0,0,1,15.14,44a5.23,5.23,0,0,1,.56-2.21,12.57,12.57,0,0,1,2.48-3.37,16.58,16.58,0,0,1,3.22-2.55c.75-.43,1.19-.46,1.2-.33s-.29.44-.76,1a31.83,31.83,0,0,0-4.06,5.32c-.6,1-.87,2.21-.55,2.68a1.8,1.8,0,0,0,1,.71l.35.2.41.13a5.72,5.72,0,0,0,.83.26,22.12,22.12,0,0,0,7.58.05A114.35,114.35,0,0,0,43,42.25c6.24-1.8,12.57-4.23,18.83-6.5,3.45-1.24,6.9-2.49,10.39-3.67,1.75-.59,3.5-1.15,5.28-1.68A33.49,33.49,0,0,1,83,29.15a11.4,11.4,0,0,1,7.06,1.07,9.19,9.19,0,0,1,2.71,2.48,13,13,0,0,1,1.58,3.22A35.21,35.21,0,0,1,95.7,46.26c0,3.45-.09,6.86,0,10.23q0,2,.24,3.87a16,16,0,0,0,.31,1.86c.06.31.16.6.23.89l.07.22.11.32c.07.21.13.43.18.65a1.14,1.14,0,0,1-.38,1.24,3.6,3.6,0,0,1-1.26.71,13.22,13.22,0,0,1-2,.48c-1.32.22-2.62.36-3.92.5l-3.39.38c-4.22.44-5.39.72-6.35.8-.22,0-.49.11-.64.12s-.16-.06-.08-.23a2.19,2.19,0,0,1,.64-.67,10.35,10.35,0,0,1,3.49-1.46A61.09,61.09,0,0,1,90,65.06c1.17-.16,2.35-.31,3.44-.55.27-.05.53-.12.78-.19a1.77,1.77,0,0,0,.31-.11h0s.06,0,0-.16l0,0a.46.46,0,0,1,0-.12l-.13-.49a9.22,9.22,0,0,1-.23-1c-.14-.65-.21-1.29-.29-1.93-.13-1.28-.2-2.54-.22-3.79-.06-2.5,0-5,0-7.42a52.54,52.54,0,0,0-.72-10.65A13.24,13.24,0,0,0,91.08,34a6.16,6.16,0,0,0-3.61-2.55Z"
/>
<path
className="cls-1"
d="M91.62,78.84c1.25-.25,2.49-.55,3.72-.86l1.84-.51L98.81,77l.17,0a.32.32,0,0,0,0-.17l0-.28,0-.73a12.57,12.57,0,0,1,0-1.36l.13-1.26.24-2.47c.14-1.64.25-3.29.29-4.94a28.3,28.3,0,0,0-.19-4.33,11.37,11.37,0,0,0-.62-2.57,2.55,2.55,0,0,0-.58-.91.8.8,0,0,0-.82-.18c-.43.14-.63-.14-.26-.69a1.45,1.45,0,0,1,1.34-.51,2.4,2.4,0,0,1,1.68,1.24,10.22,10.22,0,0,1,1,3.07,25.87,25.87,0,0,1,.35,3,35.06,35.06,0,0,1-.17,5.89c-.11,1.16-.18,2.35-.24,3.54,0,.61-.08,1.2-.07,1.72,0,.27,0,.55,0,.83l.07,1a3.67,3.67,0,0,1-.2,1.53c-.43.25-.93.44-1.39.65-.7.25-1.28.44-1.92.64q-1.89.59-3.81,1.08c-1.57.41-3.15.77-4.75,1.08a34.13,34.13,0,0,1-3.69.52,13.55,13.55,0,0,1-1.92.06,4.59,4.59,0,0,1-2.13-.52,7.71,7.71,0,0,1-2.13-2.31,16.08,16.08,0,0,1-1.36-2.64,9.89,9.89,0,0,1-.46-1.22,4,4,0,0,1-.2-1.75,1.26,1.26,0,0,1,.65-.83,1.75,1.75,0,0,1,.42-.23.68.68,0,0,1,.68.28,2.7,2.7,0,0,1,.62,1.07,21,21,0,0,0,1.92,4.16,4.82,4.82,0,0,0,1.2,1.39l0,0h0l-.2.31h0l.07-.1.13-.2h0l0,0c.07,0,.24,0,.36.07s.34,0,.5,0a4.86,4.86,0,0,0,.54,0,26.48,26.48,0,0,0,3.63-.4c1.24-.2,2.49-.47,3.74-.75Z"
/>
<path
className="cls-1"
d="M77,19.55a8,8,0,0,0-1.33-1.93c-.21-.19-.45-.31-.66-.48a4.19,4.19,0,0,0-2.68-.93,4.4,4.4,0,0,0-1.42.35,4.17,4.17,0,0,1-1.9.5c-.45,0-.68-2.38.12-2.63a17.14,17.14,0,0,1,2.11-.53,7.87,7.87,0,0,1,1.29-.05,5,5,0,0,1,1.28.27,8.87,8.87,0,0,1,2.78,1.25,8.11,8.11,0,0,1,2.08,2.35,14.28,14.28,0,0,1,.86,1.64c.4.83.64,1.71.95,2.55.23.66.57,1.28.8,1.95a2.26,2.26,0,0,1,.17.43c.13.57,0,.77-.62,1l-.43.14a1,1,0,0,1-1.12-.4,19.07,19.07,0,0,1-1.32-3.16,16.37,16.37,0,0,0-1-2.25Z"
/>
<path
className="cls-1"
d="M27.21,34.77c.28.79.57,1.59.89,2.38.11.29.27.56.38.85l1.16,3.09c.17.46.38.91.59,1.35a6.13,6.13,0,0,1,.66,1.76c.06.39-1.34.41-1.65-.21a21.48,21.48,0,0,1-1.4-3.5,19.15,19.15,0,0,0-.92-2.14c-.34-.79-.67-1.6-1-2.4-.19-.5-.39-1-.58-1.49-.3-.75-.55-1.52-.86-2.27-.23-.58-.55-1.12-.79-1.7a2.19,2.19,0,0,1-.17-.38c-.16-.49-.09-.68.3-.89l.27-.15a.66.66,0,0,1,.84.31,15.36,15.36,0,0,1,1.41,3c.29.78.6,1.57.9,2.36Z"
/>
<path
className="cls-1"
d="M49,17.22c-2.08.83-4.18,1.61-6.27,2.4-.76.29-1.5.63-2.27.91-2.69,1-5.4,2-8.07,3C31.2,24,30,24.48,28.88,25c-1.45.68-2.95,1.41-4.26,2.08-.27.16-.63,0-.5-.63a3.16,3.16,0,0,1,1.56-1.8,62.43,62.43,0,0,1,9.26-3.9c1.9-.65,3.79-1.52,5.68-2.28L46.89,16c1.28-.51,2.57-1,3.84-1.56,1.93-.82,3.87-1.63,5.73-2.54,1.45-.7,2.8-1.52,4.19-2.29l.91-.5c1.15-.61,1.58-.68,2-.49a2,2,0,0,1,.29.12c.24.14-.07.68-.84,1.31a35.38,35.38,0,0,1-7.76,4.55c-2.06.94-4.16,1.81-6.24,2.68Z"
/>
<path
className="cls-1"
d="M67.68,24.37c-.34-1-.7-2.09-1.07-3.12-.14-.38-.34-.73-.48-1.11l-1.39-4.06A16.67,16.67,0,0,0,64,14.34a5.9,5.9,0,0,1-.87-2.3c0-.53,2.38-.71,2.71.1a27.47,27.47,0,0,1,1.55,4.64,20.42,20.42,0,0,0,1.1,2.83c.4,1.05.78,2.1,1.15,3.16l.69,2c.35,1,.65,2,1,3,.28.77.69,1.47,1,2.23a5.44,5.44,0,0,1,.22.5c.2.65.1.9-.5,1.18-.13.06-.26.13-.4.18a1,1,0,0,1-1.18-.41,21,21,0,0,1-1.75-3.91c-.37-1-.74-2-1.12-3.08Z"
/>
<path
className="cls-1"
d="M59.88,20.52H59.8l-.59.17c-.41.11-.81.25-1.22.38-.81.28-1.62.58-2.43.91-.6.24-1.16.54-1.77.78-2.11.85-4.3,1.66-6.52,2.34l-2.94,1a11.7,11.7,0,0,1-3.88.82c-.82,0-.16-2.48,1.19-2.77,2.45-.58,4.86-1.26,7.39-2a38.41,38.41,0,0,0,4.46-1.83A52.69,52.69,0,0,1,58.6,18.4l.53-.15.75-.21,1.49-.38L62,19.4c.56,1.63,1.13,3.26,1.68,4.88.44,1.21,1,2.37,1.44,3.59.1.27.21.53.3.81.3,1,.21,1.41-.37,1.76a2.3,2.3,0,0,1-.4.23c-.46.2-.94-.13-1.26-.81-.94-2-1.72-4.23-2.52-6.46l-.73-2.07L60,20.8l0-.13h0v-.06h0Z"
/>
<path
className="cls-1"
d="M32.91,35.71l.42,1.42c.05.18.15.33.19.51.17.63.32,1.26.5,1.89a6.19,6.19,0,0,0,.32.81,2,2,0,0,1,.34,1.06c0,.25-1.37.38-1.53,0a8.16,8.16,0,0,1-.66-2.08A6.88,6.88,0,0,0,32,38.07c-.19-.47-.32-1-.47-1.45l-.27-.91c-.15-.45-.24-.92-.4-1.37s-.31-.66-.44-1a.83.83,0,0,1-.08-.22c-.06-.3,0-.42.29-.56l.18-.09a.56.56,0,0,1,.61.15,5.5,5.5,0,0,1,1,1.71c.21.44.33.92.5,1.38Z"
/>
<path
className="cls-1"
d="M33.7,35.9c.13.4.25.8.37,1.2,0,.15.13.28.17.43.14.52.28,1.07.42,1.59a5.46,5.46,0,0,0,.26.67,1.91,1.91,0,0,1,.29.89c0,.21-1.13.32-1.26,0A6.74,6.74,0,0,1,33.4,39,5.4,5.4,0,0,0,33,37.88c-.15-.39-.27-.8-.4-1.21l-.24-.75c-.14-.38-.23-.77-.37-1.14s-.29-.54-.4-.82a1.08,1.08,0,0,1-.08-.19c-.06-.24,0-.34.21-.47l.15-.08a.43.43,0,0,1,.5.1,4.43,4.43,0,0,1,.93,1.41,11.6,11.6,0,0,1,.45,1.16Z"
/>
<path
className="cls-1"
d="M85.33,74.08c.25-.06.45-.13.52-.44a.88.88,0,0,0-.08-.39l-.06-.37a1.16,1.16,0,0,0-.21-.34,2,2,0,0,0-.82-.61.93.93,0,0,0-.77,0c-.21.15-.22.29-.42.69-.07.11-.45.16-.84,0a1.44,1.44,0,0,1-.55-.38.87.87,0,0,1-.12-.71,2.24,2.24,0,0,1,.93-1.24,2.78,2.78,0,0,1,1.3-.43,3.22,3.22,0,0,1,2.16.56,7.3,7.3,0,0,1,1.07.9,4.61,4.61,0,0,1,.72,1.19,3.25,3.25,0,0,1-.48,3,3.36,3.36,0,0,1-1.46,1.06,3.31,3.31,0,0,1-2.72-.08A3,3,0,0,1,82,74.93a2.21,2.21,0,0,1-.16-.52c0-.58.21-.77.91-.8.16,0,.32,0,.48,0a2,2,0,0,1,1.14.41c.06.06.12.13.17.17l.13,0a.48.48,0,0,0,.18,0c.08,0,.08-.07.08-.07s0,0,.06,0a.82.82,0,0,0,.32-.12Z"
/>
<path
className="cls-1"
d="M84.86,74.27c.12,0,.15-.27.09-.49s-.1-.11-.13-.19a2.51,2.51,0,0,0-.42-1,.35.35,0,0,0-.28-.14c-.05,0-.11.16-.25.1a2.42,2.42,0,0,1-.51-.73c-.22-.4-.27-.92,0-1.07a1.4,1.4,0,0,1,.33-.15,1.61,1.61,0,0,1,.44,0,2.56,2.56,0,0,1,.7,0,1.73,1.73,0,0,1,.94.55c.26.31.66.43.91.75a3.77,3.77,0,0,1,.65,1.19,2.88,2.88,0,0,1,.15,1,2.12,2.12,0,0,1-.76,1.48c-.27.25-.51.59-.78.8a1.39,1.39,0,0,1-.19.15c-.12,0-.21,0-.31-.17a3.12,3.12,0,0,1-.15-.39c0-.1-.07-.22-.11-.35l-.09-.33a3.06,3.06,0,0,1-.07-.55l0-.41A1,1,0,0,1,85,74a1.31,1.31,0,0,0,.07-.55,3,3,0,0,0,.29.44l.15.16a.39.39,0,0,0,.1.08c.17.08-.14-.09-.73.12Z"
/>
<path
className="cls-1"
d="M88,81.45a24.29,24.29,0,0,0,2.53-.32c.31,0,.61-.17.92-.23,1.09-.21,2.19-.46,3.28-.75a14.12,14.12,0,0,0,1.43-.48A5.67,5.67,0,0,1,98,79.14c.41,0,.25,1.26-.39,1.56a18.45,18.45,0,0,1-3.76,1.15c-.79.14-1.55.47-2.35.67a26.12,26.12,0,0,1-2.66.55c-.56.07-1.12.15-1.69.18s-.85,0-1.29,0a11.53,11.53,0,0,1-1.31-.09,6.28,6.28,0,0,1-1-.16c-.17,0-.35-.06-.52-.11l-.5-.23c-.14-.08-.3-.13-.43-.22-.47-.42-.53-.64-.34-1,0-.08.09-.16.14-.23a.77.77,0,0,1,.83-.16,16.89,16.89,0,0,0,2.85.39,9.24,9.24,0,0,0,1.18,0A10.46,10.46,0,0,0,88,81.41Z"
/>
<path
className="cls-1"
d="M26.49,53.14l-1.13.11c-.14,0-.27,0-.41,0-.5,0-1,0-1.48,0h-.65a2.31,2.31,0,0,1-.83-.1c-.17-.06.12-.49.41-.5.52,0,1,0,1.59,0a4.63,4.63,0,0,0,1-.14l1.1-.16.68-.12c.34-.07.69-.12,1-.22s.51-.17.77-.25l.17-.06c.21,0,.29,0,.38.19a.75.75,0,0,1,.06.13.31.31,0,0,1-.15.39,3.64,3.64,0,0,1-1.38.57l-1.12.19Z"
/>
<path
className="cls-1"
d="M76.44,40l-1.17.15-.43.08c-.5.06-1,.12-1.51.21-.23,0-.44.1-.66.16a3.52,3.52,0,0,1-.84.19c-.19,0-.09-.49.22-.62a8.37,8.37,0,0,1,1.69-.49,7.83,7.83,0,0,0,1.05-.3c.38-.1.78-.18,1.17-.26l.72-.15,1.1-.22c.28-.05.55-.17.83-.24l.18,0c.23-.05.32,0,.4.22a.94.94,0,0,1,.06.15.38.38,0,0,1-.17.43,4.88,4.88,0,0,1-1.47.57L76.45,40Z"
/>
<path
className="cls-1"
d="M44.57,49.43l-.77.07-.28,0c-.33,0-.67.06-1,.11a3.34,3.34,0,0,0-.43.1,2.07,2.07,0,0,1-.55.11c-.12,0-.06-.34.14-.42a4.77,4.77,0,0,1,1.12-.31,5.84,5.84,0,0,0,.69-.18c.25-.07.51-.11.77-.16l.48-.08.72-.13c.18,0,.36-.11.54-.16l.12,0c.15,0,.2,0,.26.16l0,.1a.26.26,0,0,1-.11.3,3,3,0,0,1-1,.38l-.76.1Z"
/>
<path
className="cls-1"
d="M99.49,91s12.18-.88,14.94,4.77c3.94,8-25.72,15.38-33.94,17-9.44,1.85-7.43,1.59-7.43,1.59s20.5-5.4,23.43-9.41S100.21,93.08,99.49,91Z"
/>
<path
className="cls-1"
d="M54.63,40.73c-3.88,1.28-7.8,2.5-11.75,3.6-1.45.4-2.89.83-4.35,1.18a68.56,68.56,0,0,1-7.85,1.4,23.57,23.57,0,0,1-8.11-.21,13.8,13.8,0,0,1-1.79-.58,7.26,7.26,0,0,1-1.69-1.06,3,3,0,0,1-.93-2,4.66,4.66,0,0,1,.34-2,11.58,11.58,0,0,1,2.65-3.89,13.82,13.82,0,0,1,3.71-2.75c.95-.39.89,0,.39.66a37.37,37.37,0,0,1-2.4,3,14.52,14.52,0,0,0-2.31,3.36A3.21,3.21,0,0,0,20.19,43a1.13,1.13,0,0,0,.6.86A8.58,8.58,0,0,0,24.51,45a26,26,0,0,0,4.34.11,55.22,55.22,0,0,0,10.81-2c3.94-1,7.85-2.22,11.75-3.49,2.39-.79,4.79-1.59,7.17-2.43,3.6-1.28,7.23-2.56,10.79-3.89,2.76-1,5.44-2.17,8.21-3.14.61-.22,1.21-.44,1.83-.64,2.33-.69,3.16-.61,3.76-.36a2.16,2.16,0,0,1,.4.18c.29.24-.59.74-2.18,1.48-2.39,1-4.87,2-7.39,3l-7.7,2.89q-5.77,2.11-11.65,4.13Z"
/>
<path
className="cls-1"
d="M29.58,115.23a12.62,12.62,0,0,0,3.25,2.11c.42.23.9.32,1.34.51a13.16,13.16,0,0,0,5,.86,23.41,23.41,0,0,0,2.34-.22,11.87,11.87,0,0,1,3.1-.13c.32,0,.27.34,0,.66a2.17,2.17,0,0,1-1.27.75,19.94,19.94,0,0,1-6.33.4,23.32,23.32,0,0,1-3.95-.83,15.21,15.21,0,0,1-3.92-2c-.36-.28-.72-.56-1.07-.85s-.67-.61-1-.93a13.86,13.86,0,0,1-2.39-3.34,12,12,0,0,1-1.23-2.93c-.05-.23-.11-.45-.15-.69-.1-.88.08-1.17.46-1.36a2,2,0,0,1,.28-.11c.3-.08.6.25.77.78s.31.79.44,1.18l.52,1.14a14.06,14.06,0,0,0,1.26,2.15,13.81,13.81,0,0,0,2.52,2.84Z"
/>
</g>
</svg>
);
};
export const ChartIcon = () => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 128 128"
className="w-12 fill-primary"
>
<title>Free Icons</title>
<g
id="Layer_10"
data-name="Layer 10"
>
<path
className="cls-1"
d="M21.55,80.68c.08-4.89.14-9.73.08-14.61l-.11-5.33c-.07-6.26-.16-12.52-.39-18.78-.1-2.78-.27-5.57-.5-8.31-.33-3.52-.62-7.07-.9-10.53-.07-1.08.21-1,.77-.19a10.42,10.42,0,0,1,1.64,4.58A107.94,107.94,0,0,1,23,38.41q.24,5.45.26,10.93c0,4.37.25,8.92.33,13.39.09,4.91.13,9.84.08,14.76,0,3-.06,6,0,9.06.05,4.57.13,9.16.5,13.67.29,3.51.81,6.92,1.4,10.34.14.75.27,1.49.41,2.24.49,2.82.54,3.73,0,4.45a3.13,3.13,0,0,1-.35.48c-.43.36-1-.72-1.54-2.78a104.72,104.72,0,0,1-2.42-19.44c-.23-4.94-.19-9.89-.18-14.82Z"
/>
<path
className="cls-1"
d="M49.41,104.67c4.89.25,9.8.35,14.7.3,1.79,0,3.57-.14,5.36-.17,6.3-.16,12.61-.54,18.87-1.26,2.78-.33,5.56-.77,8.29-1.27,1.75-.35,3.5-.69,5.24-1.1s3.5-.68,5.26-1c1.1-.18,1,.13.22.72A15,15,0,0,1,103,103c-3.58.92-7.22,1.54-10.87,2.12s-7.33.88-11,1.08c-4.43.27-9,.68-13.55.81q-7.45.24-14.93,0c-3.06-.1-6.12-.23-9.18-.42l-13.84-1c-3.57-.25-7.07-.39-10.61-.67-.77-.07-1.54-.1-2.32-.19-2.9-.31-3.8-.63-4.32-1.38a2.82,2.82,0,0,1-.34-.51c-.2-.56,1-.81,3.14-.68,6.27.4,12.85.93,19.5,1.42,4.95.36,9.87.79,14.81,1Z"
/>
<path
className="cls-1"
d="M34.75,75.38c0,2.72,0,5.45,0,8.17l.11,3c.09,3.5.14,7,.49,10.46,0,.36.09.73.16,1.07,0,.12,0,.19.07.28s.07.18.17.19a1.35,1.35,0,0,0,.29,0,4.41,4.41,0,0,0,.53,0c.37,0,.77,0,1.15,0,1-.07,1.94-.22,2.91-.35s2-.2,2.93-.31c.57-.06.62.25.18.72A5.16,5.16,0,0,1,41.27,100c-1,.17-1.94.32-2.93.43-.5,0-1,.09-1.52.1a7.6,7.6,0,0,1-.82,0,3.49,3.49,0,0,1-.66-.11c-.22-.06-.44-.11-.66-.19-.89-.41-1-2-1-2.27-.07-.56-.12-1.11-.16-1.66-.07-1.09-.1-2.17-.11-3.26,0-2.47-.22-5-.28-7.52C33,82.7,33,79.94,33,77.18l.07-5.09c0-1.29.07-2.58.14-3.87,0-.65.07-1.29.14-1.94a8.62,8.62,0,0,1,.15-1.11c.08-.43.22-.9.67-1a3.41,3.41,0,0,1,1,0l.77.06,1.46.13a25.11,25.11,0,0,0,2.87,0c.41,0,.81,0,1.21-.09,1.47-.17,1.76-.28,2.26-.13.11,0,.25,0,.35.06s.18.25,0,.56a2.77,2.77,0,0,1-1.33.88,14.22,14.22,0,0,1-5.64.31l-1.38-.12-.61,0h0s0,0,0,0c-.05.41-.09.86-.12,1.31-.15,2.67-.19,5.44-.19,8.18Z"
/>
<path
className="cls-1"
d="M44.13,80.37l-.1,3.7c0,.45,0,.9,0,1.35,0,1.58-.11,3.17-.13,4.75,0,.71,0,1.41.07,2.11l.1,1.34A7.93,7.93,0,0,1,44,94.93a.28.28,0,0,1-.08.12l-.06,0h0l-.13.05-.06,0c.13,0,.07,0,0,0h-.11a.68.68,0,0,1-.23-.11,2,2,0,0,1-.85-1.17,30,30,0,0,1-.06-5.53c.09-1.11,0-2.25,0-3.39l0-3.73,0-2.3c0-1.16,0-2.32,0-3.48,0-.89-.15-1.77-.22-2.66,0-.2,0-.39-.05-.59,0-.74.12-1,.61-1.11a2,2,0,0,1,.33-.08c.37,0,.67.26.75.78a30,30,0,0,1,.3,4.88l0,3.72Z"
/>
<path
className="cls-1"
d="M56.93,68c0,3.21,0,6.43.09,9.64l.12,3.52c.09,4.13.17,8.27.41,12.38.06.92.13,1.83.24,2.73l.09.66.06.33,0,.18c0,.09,0,.23.14.27a1.12,1.12,0,0,0,.32,0h.73l.84,0,1.72-.18c1.14-.16,2.31-.22,3.44-.35.68-.08.72.23.18.72a6.51,6.51,0,0,1-3,1.4,26,26,0,0,1-3.74.37l-.31,0a3.4,3.4,0,0,1-.45,0,4.21,4.21,0,0,1-.81-.23c-.1-.08-.27-.09-.32-.24a3.7,3.7,0,0,1-.28-.28,2.51,2.51,0,0,1-.31-.79l-.08-.43,0-.25L56,96.87,55.88,96c-.19-2.44-.24-4.84-.25-7.26,0-2.9-.21-5.9-.27-8.85q-.11-4.87-.13-9.74v-6c0-3,0-6.06.16-9.09a13,13,0,0,1,.18-2,1.36,1.36,0,0,1,.21-.54.89.89,0,0,1,.49-.23,5.26,5.26,0,0,1,1.2,0c1.16.11,2.28.22,3.4.25.49,0,1,0,1.45,0A14.79,14.79,0,0,1,65,52.39c.12,0,.27,0,.38,0s.2.26-.07.61a3.06,3.06,0,0,1-1.62.93c-2.24.56-4.5.16-6.52,0A37,37,0,0,0,57,58.24c0,3.22,0,6.47,0,9.72Z"
/>
<path
className="cls-1"
d="M65.74,73.72,65.67,79c0,.64,0,1.28,0,1.92l-.09,6.73c0,1,0,2,.08,3l.11,1.9a14.12,14.12,0,0,1-.09,1.87.48.48,0,0,1-.07.18s0,.07-.29.14l.12,0H65.4l-.1,0a.71.71,0,0,1-.24-.16,3.22,3.22,0,0,1-.85-1.67,61.8,61.8,0,0,1-.1-7.82c.09-1.57,0-3.19,0-4.8V71.65c0-1.64,0-3.29,0-4.92,0-1.27-.17-2.51-.25-3.77,0-.27,0-.55-.06-.83,0-1,.12-1.39.6-1.58.11,0,.22-.1.33-.13.38-.07.67.36.75,1.09a60,60,0,0,1,.37,6.93v5.28Z"
/>
<path
className="cls-1"
d="M79.38,59.1q0,5.84.16,11.67L79.69,75c.12,5,.25,10,.5,15,.11,2.21.3,4.45.58,6.59,0,.25,0,.29.07.4s0,.2.17.2l.2,0h.26l.85,0c.58,0,1.16-.08,1.75-.15,1.17-.11,2.36-.2,3.53-.34.81-.11.83.21.16.73a8.66,8.66,0,0,1-3.63,1.45c-.59.08-1.18.14-1.79.19-.3,0-.62,0-.94,0a6.43,6.43,0,0,1-.77-.05,7.69,7.69,0,0,1-.79-.21c-.1-.08-.23-.12-.29-.24a.7.7,0,0,1-.26-.28,2.43,2.43,0,0,1-.27-.77l-.09-.43,0-.25-.06-.45c-.08-.6-.15-1.18-.19-1.77-.1-1.17-.16-2.34-.22-3.5-.1-2.34-.16-4.67-.18-7,0-3.5-.26-7.13-.35-10.7-.1-3.92-.16-7.85-.2-11.78l0-7.25c0-3.66,0-7.34.17-11,0-.88.07-1.75.14-2.64l.06-.66,0-.34c0-.16.06-.32.09-.48a2.1,2.1,0,0,1,.34-.84.79.79,0,0,1,.77-.27c.92.13,1.29.18,1.83.24s1,.11,1.55.14,1.18.06,1.77.07a17.79,17.79,0,0,0,2.2-.09c.44,0,.65,0,.94-.08a1.79,1.79,0,0,0,.39-.13c.09,0,.16,0,.18.13a.88.88,0,0,1-.18.6,3.11,3.11,0,0,1-2,1.06,14.18,14.18,0,0,1-3.37.15c-.56,0-1.11-.1-1.66-.17s-1.36-.2-1.17-.15c0,0,0,0,0,.06s0,0,0,.08l0,.52c-.07.7-.1,1.44-.14,2.19-.06,1.48-.09,3-.11,4.52,0,3.89,0,7.83,0,11.75Z"
/>
<path
className="cls-1"
d="M88.36,64.82l-.09,7.39,0,2.69c0,3.17-.07,6.34-.11,9.51,0,1.4,0,2.81.07,4.21,0,.89.07,1.79.1,2.69s0,1.82-.09,2.65a.61.61,0,0,1-.08.26l-.07.08,0,0-.17.06s0,0,0,0c.21-.07.08,0,.1,0h0l-.1,0a.89.89,0,0,1-.24-.24,5.47,5.47,0,0,1-.84-2.38c-.17-3.66-.23-7.32-.07-11,.09-2.21,0-4.5,0-6.76V66.45l0-4.58c0-2.32,0-4.64,0-6.94,0-1.78-.17-3.53-.25-5.3,0-.39,0-.77-.06-1.17,0-1.45.12-1.94.6-2.23.12-.06.23-.15.34-.19.37-.11.65.48.74,1.53.29,3.13.35,6.46.37,9.79v7.46Z"
/>
<path
className="cls-1"
d="M33.63,86.13l.1-2.6.15-2.6c0-.63,0-1.26,0-1.89.14-2.24.31-4.47.38-6.71,0-1,0-2-.07-3a10.71,10.71,0,0,1,.12-3.78c.11-.4.58-.38,1.14-.09a4.47,4.47,0,0,1,.91.64,1.67,1.67,0,0,1,.6,1,33.87,33.87,0,0,1,.52,3.85,31.9,31.9,0,0,1-.13,3.9,36,36,0,0,0,.15,4.75c0,1.75.06,3.5,0,5.25l0,3.23c0,1.63-.06,3.27,0,4.89.08,1.25.42,2.48.58,3.72a8.11,8.11,0,0,1,.12.82,1.52,1.52,0,0,1-.32,1.11,1.75,1.75,0,0,1-1,.49,4.34,4.34,0,0,1-.6.14,1.65,1.65,0,0,1-1.64-1,11.41,11.41,0,0,1-.86-3.35c-.15-1.14-.21-2.31-.26-3.48-.06-1.73,0-3.48,0-5.23Z"
/>
<path
className="cls-1"
d="M56,81.05l.08-3.42.14-3.42c0-.83,0-1.66,0-2.49.12-2.94.28-5.87.34-8.81,0-1.3,0-2.6-.06-3.89a21.76,21.76,0,0,1,.09-5c.09-.52.5-.48,1-.07a4.06,4.06,0,0,1,.81.87A2.54,2.54,0,0,1,59,56.13c.2,1.69.4,3.38.47,5.08s0,3.4-.12,5.11c-.15,2.05.09,4.17.12,6.26,0,2.29,0,4.59,0,6.89l-.05,4.24c0,2.15,0,4.3.05,6.42.07,1.65.37,3.27.52,4.9,0,.36.1.71.11,1.08a2.53,2.53,0,0,1-.28,1.44,1.48,1.48,0,0,1-.83.64,4.25,4.25,0,0,1-.53.19c-.58.13-1.1-.42-1.45-1.38a36.15,36.15,0,0,1-1-9c-.05-2.29,0-4.59,0-6.89Z"
/>
<path
className="cls-1"
d="M78.45,75.22l.09-4.47.15-4.48c0-1.08,0-2.17,0-3.26.13-3.83.29-7.66.36-11.5,0-1.7,0-3.4,0-5.09a38,38,0,0,1,.09-6.49c.09-.67.5-.62,1-.07A5.63,5.63,0,0,1,80.91,41a4.1,4.1,0,0,1,.53,1.68c.2,2.21.4,4.42.46,6.64s0,4.44-.13,6.68c-.15,2.67.08,5.44.11,8.18,0,3,0,6,0,9l-.05,5.54c0,2.8-.06,5.61,0,8.39.07,2.16.37,4.27.52,6.4,0,.47.09.93.11,1.41,0,1.76-.35,2.33-1.11,2.71a3.59,3.59,0,0,1-.53.25c-.58.17-1.1-.55-1.45-1.82a61.48,61.48,0,0,1-1-11.85c0-3,0-6,0-9Z"
/>
<path
className="cls-1"
d="M113.37,98.22a.59.59,0,0,0,.16-.08l.1-.08c.05,0,.05,0,0-.06l-.16-.08-.12-.06s-.32-.11-.49-.17c-.61-.19-1.23-.34-1.83-.56-2.1-.77-4.14-1.67-6.17-2.59l-2.73-1.18a9,9,0,0,1-3.3-2.1c-.3-.35.06-.53.56-.62a3.06,3.06,0,0,1,1.75.11c2.21.93,4.5,2,6.8,3.07a36.68,36.68,0,0,0,4.38,1.55l.9.28.45.14.25.07.39.1c.53.11,1,.26,1.55.35l1.59.27,0,.27-.3.42c-.21.28-.4.52-.6.77s-.49.59-.76.87l-.87.82c-.5.44-.86.72-1.3,1.08-1.29,1-2.62,1.94-3.87,2.93-1,.76-1.86,1.62-2.77,2.43-.2.18-.39.38-.59.55-.78.64-1.12.72-1.65.4a3.28,3.28,0,0,1-.37-.22c-.35-.29-.26-.84.24-1.42a32.47,32.47,0,0,1,5.13-4.56l2.06-1.52,1-.77.48-.39c.09-.06.05,0,.08,0Z"
/>
<path
className="cls-1"
d="M72.14,35A81.06,81.06,0,0,1,62,39.5c-1.27.44-2.51,1-3.78,1.38A102.21,102.21,0,0,1,44.49,44l-3.1.45c-1,.14-2.07.23-3.1.33-1.32.11-2.65.19-4,.2a18.71,18.71,0,0,1-4-.32c-.84-.2-.66-.32.05-.42.35,0,.84-.13,1.44-.24s1.27-.17,2-.22c1.32-.05,2.64-.26,4-.4l2-.29c.66-.08,1.32-.16,2-.28,2.63-.4,5.26-.91,7.88-1.47A68.88,68.88,0,0,0,59,38.42c1.67-.68,3.39-1.25,5-2.05s3.33-1.42,4.9-2.32l3-1.56c1-.49,1.9-1.15,2.85-1.72a73.78,73.78,0,0,0,8.24-5.84c1-.88,1.9-1.77,2.81-2.67l1.38-1.34c.46-.45.86-1,1.29-1.43s.73-.85,1.12-1.26c1.44-1.54,2-1.89,2.88-1.76a4.32,4.32,0,0,1,.56.1c.55.21.27,1.14-.71,2.4a39.79,39.79,0,0,1-4.85,5.42c-.91.83-1.84,1.66-2.77,2.49s-2,1.51-3,2.27L79.39,30.8c-.76.54-1.59,1-2.38,1.49-1.6,1-3.15,2-4.84,2.81Z"
/>
<path
className="cls-1"
d="M96.44,12.56l0-.14,0-.08c0-.05,0-.11,0-.18s-.08,0-.13,0a1.44,1.44,0,0,0-.29.11c-.48.27-1,.57-1.46.81A20.77,20.77,0,0,1,89,14.8c-.86.14-1.72.29-2.57.39a11.4,11.4,0,0,1-3.3.07c-.34,0-.29-.36,0-.7a2.31,2.31,0,0,1,1.38-.8c2.12-.29,4.17-.65,6.26-1.08a14.74,14.74,0,0,0,3.6-1.49l.74-.4,1.09-.62c.4-.22.78-.44,1.16-.63A11.33,11.33,0,0,1,98.44,9l-.13,1.79-.13,2-.11,1.39a26.59,26.59,0,0,1-.72,4.22,18.25,18.25,0,0,1-1,3.19,5.79,5.79,0,0,1-.31.67c-.46.81-.78.95-1.28.82-.11,0-.23-.06-.34-.11-.35-.17-.4-.65-.14-1.19a22.76,22.76,0,0,0,1.68-5.18c.12-.69.24-1.39.31-2.11,0-.35.07-.72.1-1.08l.06-.87Z"
/>
</g>
</svg>
);
};
export const MagnifierIcon = () => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 128 128"
className="w-12 fill-primary"
>
<title>Free Icons</title>
<g
id="Layer_46"
data-name="Layer 46"
>
<path
className="cls-1"
d="M60.58,28c1.89.06,3.8.09,5.7.09l2.08,0q3.66,0,7.34-.13c1.08,0,2.17-.11,3.25-.18,1.38-.05,2.76-.21,4.16-.14.43,0,.38,0,0,.16a8.62,8.62,0,0,1-1.81.48,68.81,68.81,0,0,1-8.5.56c-1.71,0-3.49.11-5.24.14-1.92,0-3.84,0-5.77,0l-3.55-.08c-1.79,0-3.59-.13-5.36-.22-1.39-.06-2.74-.08-4.11-.17l-.91-.05c-1.12-.14-1.46-.29-1.67-.57a1.77,1.77,0,0,1-.14-.16c-.09-.11.4-.32,1.22-.31,2.43.07,5,.27,7.54.39,1.91.09,3.83.17,5.74.2Z"
/>
<path
className="cls-1"
d="M58.21,28.25,55.88,28,55,28c-1-.11-2-.21-3-.35l-1.32-.13A7.5,7.5,0,0,1,49,27.23c-.19-.06-.1-.18.08-.29a1.25,1.25,0,0,1,.76-.22,26.71,26.71,0,0,1,3.44.27c.69.11,1.41.12,2.12.18l2.33.19,1.44.12c.73,0,1.46.1,2.18.12.56,0,1.12,0,1.67,0h.37c.45,0,.59.07.69.29a.94.94,0,0,1,.06.15c0,.17-.15.31-.49.36a14.62,14.62,0,0,1-3.11.07c-.78,0-1.56-.09-2.34-.15Z"
/>
<path
className="cls-1"
d="M55.41,88.66A15.53,15.53,0,0,0,61.2,95.9a18,18,0,0,0,3,1.69,17.28,17.28,0,0,0,12,1,17.58,17.58,0,0,0,5-2.22,23.83,23.83,0,0,0,5.14-4.73c.47-.55.77-.25.71.5a4.94,4.94,0,0,1-1.58,3,19.84,19.84,0,0,1-14.14,5.57,23.55,23.55,0,0,1-4.69-.61,20.07,20.07,0,0,1-4.42-1.72,18.08,18.08,0,0,1-7.41-7.12A16.32,16.32,0,0,1,53,85.22a18.1,18.1,0,0,1,1.46-9.39,20,20,0,0,1,4.09-6.07,15.5,15.5,0,0,1,1.19-1.1c1.59-1.28,2.26-1.45,2.83-1.31a1.7,1.7,0,0,1,.38.12c.33.22-.26.79-1.33,1.65a18.94,18.94,0,0,0-6.7,10.28,15.76,15.76,0,0,0,.57,9.24Z"
/>
<path
className="cls-1"
d="M51.72,117.14c1.84.13,3.69.22,5.53.28l2,0q3.56.14,7.13.18c1.06,0,2.12,0,3.16-.06a28.81,28.81,0,0,1,4,0c.42.07.37.3,0,.59a3,3,0,0,1-1.77.68,71.46,71.46,0,0,1-8.28,0c-1.66-.09-3.39,0-5.09,0-1.86,0-3.73-.1-5.6-.17l-3.45-.19c-1.74-.1-3.49-.25-5.22-.41-1.35-.12-2.68-.2-4-.42a5.74,5.74,0,0,1-.9-.18,2.54,2.54,0,0,1-1.15-.49.74.74,0,0,1-.31-.62,1.55,1.55,0,0,1,0-.31c.09-.31.61-.38,1.26-.19,2.16.42,4.62.65,7.08.88,1.83.15,3.69.3,5.54.39Z"
/>
<path
className="cls-1"
d="M23.72,104.17c-.23-.08-10,3-12.25,6.71s19,8,35,6.48L24,109.76Z"
/>
<path
className="cls-1"
d="M61.21,36.17c-4.82,1.74-12.35-1.35-14.67-2.75s-4.65-7.22-4.65-7.22l8.26.44S53.39,35.06,61.21,36.17Z"
/>
<path
className="cls-1"
d="M54.26,52.54A60.85,60.85,0,0,0,40.31,66.29a92.51,92.51,0,0,0-5.57,8.21,82.37,82.37,0,0,0-4.54,8.81,67.35,67.35,0,0,0-4.29,13.74c-.21,1-.35,2.09-.53,3.13s-.23,2.1-.35,3.15l-.17,3.16,0,1.59a4.59,4.59,0,0,0,0,.85L27.22,110c1,.47,2,.76,3,1.15,2,.8,4,1.3,6.08,1.94a126.74,126.74,0,0,0,25.38,3.83,143.43,143.43,0,0,0,22.81-.59,138.46,138.46,0,0,0,28.41-6.16c2.89-.89,2.67-.41.4.9-.57.33-1.27.71-2.08,1.13a20.66,20.66,0,0,1-2.77,1.27q-1.57.6-3.42,1.23c-.61.2-1.24.42-1.9.61l-2,.49a133.29,133.29,0,0,1-30,3.6,140.45,140.45,0,0,1-30.14-3l-4.45-1.08c-1.49-.38-3-.86-4.45-1.29s-2.93-1-4.41-1.55c-.74-.24-1.44-.61-2.17-.92l-2.72-1.23a4.91,4.91,0,0,1-.05-1l0-.87,0-1.18c0-.79,0-1.58.05-2.37,0-1.58.22-3.14.36-4.71A66.71,66.71,0,0,1,25,91.06a77,77,0,0,1,8.39-18.72,87.13,87.13,0,0,1,5.83-8.43A70.89,70.89,0,0,1,46,56.24a48.83,48.83,0,0,1,10.09-7.68,38.07,38.07,0,0,1,5.8-2.67,31.16,31.16,0,0,1,6.25-1.45,27.84,27.84,0,0,1,9.67.53,31.8,31.8,0,0,1,9,3.64,50.62,50.62,0,0,1,14,12.94,84.72,84.72,0,0,1,7.82,12.35,94.47,94.47,0,0,1,5.74,13.36c.68,2,1.33,4,1.84,6.14a41.26,41.26,0,0,1,1.38,8.43,8.82,8.82,0,0,1-.48,3.84,7.34,7.34,0,0,1-.48,1.12c-.59.72-.73-2.44-1.83-8A93.23,93.23,0,0,0,106,74.49a79.27,79.27,0,0,0-7-11.19,52.82,52.82,0,0,0-9.08-9.51c-5-4.06-11.12-6.87-17.5-7.06s-12.69,2.13-18,5.85Z"
/>
<path
className="cls-1"
d="M88.87,83c-.27,21-34.27,22.53-35.3,1.17A18.87,18.87,0,0,1,66.38,65.86C77.86,62.18,88.23,71.8,88.87,83c.07,1.28,2.07,1.29,2,0C90.2,71.23,80.23,61.16,68,63.42c-9.55,1.75-16.79,11.11-16.39,20.77,1,24,39,22.4,39.3-1.17A1,1,0,0,0,88.87,83Z"
/>
<path
className="cls-1"
d="M73.13,81.46c-.57.86-1.15,1.75-1.76,2.57-.22.3-.38.65-.6,1l-2.35,3.28c-.35.49-.61,1-.91,1.55a11.29,11.29,0,0,1-.57,1,4,4,0,0,1-.84.87c-.22.16-.46-.07-.67-.44a2.08,2.08,0,0,1-.34-1.36,13.57,13.57,0,0,1,2.33-4c.6-.74,1-1.64,1.57-2.45s1.26-1.75,1.93-2.57l1.22-1.55c.61-.78,1.24-1.56,1.8-2.36.44-.62.8-1.29,1.23-1.91.1-.14.18-.28.29-.42a1.12,1.12,0,0,1,.53-.44.66.66,0,0,1,.46,0,.85.85,0,0,1,.19.06c.18.09.17.4.06.86a36.13,36.13,0,0,1-1.9,3.71c-.53.91-1.09,1.8-1.63,2.71Z"
/>
<path
className="cls-1"
d="M72.51,45V41.46a1.38,1.38,0,0,0-2.75,0V45a1.38,1.38,0,0,0,2.75,0Z"
/>
<path
className="cls-1"
d="M78.21,38.25c-3.61.17-7.21.1-10.79,0-1.3,0-2.61,0-3.91-.08C59,38,54.16,37.77,49.7,36a17,17,0,0,1-2.84-1.47,13.76,13.76,0,0,1-2.45-2A15.52,15.52,0,0,1,42,29.22c-.65-1.17-1.09-2.42-1.68-3.49-.38-.61-.22-.74.46-.36a11.33,11.33,0,0,1,2.47,2.57c2.73,4.34,7,6.7,12.17,7.61a59.49,59.49,0,0,0,9.63.63c3.59.1,7.17.2,10.74.11,2.19,0,4.39-.15,6.57-.35a38.47,38.47,0,0,0,9.71-1.74,8.24,8.24,0,0,0,3.09-1.84,20.32,20.32,0,0,0,2.35-2.82l1-1.37C99.74,26.47,100.36,26,101,26a2.09,2.09,0,0,1,.44,0c.4.13,0,.9-.81,2.14a27.7,27.7,0,0,1-4.39,5.76,9.48,9.48,0,0,1-1.64,1.2c-.3.18-.62.32-.93.48s-.59.25-.89.35A25.44,25.44,0,0,1,89.13,37a52.14,52.14,0,0,1-5.46.81c-1.8.2-3.63.36-5.45.46Z"
/>
<path
className="cls-1"
d="M61.61,26.1q4.2.22,8.4.27c1,0,2-.05,3.06,0,3.61,0,7.21-.08,10.81-.25,1.6-.09,3.2-.25,4.77-.46,1-.07,2-.25,3-.36.5-.06,1-.12,1.51-.2s1-.07,1.53-.11.58,0,.09.31l-1,.61a6.6,6.6,0,0,1-1.54.57c-1,.22-2.06.49-3.1.67s-2.09.3-3.14.4c-2.1.2-4.21.35-6.33.36-2.53,0-5.15.2-7.74.23-2.84,0-5.69,0-8.53-.08l-5.24-.22c-2.65-.13-5.3-.33-7.93-.54-2-.15-4.06-.24-6.09-.47-.45-.06-.89-.09-1.34-.16l-.58-.1-.47-.16a5.7,5.7,0,0,1-.68-.31,2.09,2.09,0,0,1-.41-.32,2,2,0,0,1-.22-.4c-.05-.13-.13-.24-.15-.32-.09-.24.71-.6,1.88-.48,3.5.33,7.22.72,11,1,1.4.11,2.8.21,4.21.29s2.82.15,4.23.21Z"
/>
<path
className="cls-1"
d="M73.91,82.23a2.62,2.62,0,1,1-4.3-2A2.64,2.64,0,0,1,73.91,82.23Z"
/>
<path
className="cls-1"
d="M67.82,15.63c.15,0,0,.19-.2.51a1.45,1.45,0,0,1-.42.35,1.35,1.35,0,0,1-.34,0,5.47,5.47,0,0,1-.82-.62,1.87,1.87,0,0,1-.42-.56c-.21-.41-.42-.82-.58-1.22a.93.93,0,0,1-.05-.29,2,2,0,0,0-.22-.93c0-.05,0-.11-.11-.13a2.2,2.2,0,0,1-.38-.94c0-.28,0-.55,0-.83,0,0,0-.06,0-.12a.26.26,0,0,0,.09-.28,1.45,1.45,0,0,1,0-.36.76.76,0,0,1,.12-.24.65.65,0,0,1,.3-.15c.09,0,.17-.07.26-.12l.1,0a3.43,3.43,0,0,1,.86.49s.52.94.56,1,0,.12,0,.19.36.74.36.77.13.29,0,.49c0,0,0,.06,0,.09a4.25,4.25,0,0,1,.17.77,1.49,1.49,0,0,0,.14.37s0,0,0,.08,0,.07,0,.09a2.83,2.83,0,0,0,.39.8c0,.05.06.42.12.46S67.76,15.62,67.82,15.63Z"
/>
<path
className="cls-1"
d="M79.73,20.75c0,.15-.21.08-.56-.16a2.05,2.05,0,0,1-.42-.41c0-.11-.1-.22-.13-.3s.13-.53.15-.71a1.16,1.16,0,0,1,.19-.44c.17-.27.33-.57.5-.86a.43.43,0,0,1,.16-.17,1.33,1.33,0,0,0,.5-.63c0-.05,0-.08,0-.15s.34-.76.44-.81.44-.31.67-.45c0,0,0-.07.12-.05s.21,0,.27-.08a.73.73,0,0,1,.29-.19.9.9,0,0,1,.27,0,.87.87,0,0,1,.28.25c0,.09.15.15.24.23l.09.08a3,3,0,0,1,0,.78l-.17.37a3.3,3.3,0,0,0-.18.45c0,.05-.07.06-.12.09s-.23.64-.25.66-.1.26-.31.29c0,0,0,0-.06.06a2.22,2.22,0,0,1-.44.58,2.69,2.69,0,0,0-.19.32l-.07,0s-.06,0-.07.06a5.92,5.92,0,0,0-.51.76c0,.07-.39.24-.43.32S79.73,20.69,79.73,20.75Z"
/>
</g>
</svg>
);
};
+129
View File
@@ -0,0 +1,129 @@
import { useState } from "react";
import { Link } from "react-router-dom";
import {
NavigationMenu,
NavigationMenuItem,
NavigationMenuList,
} from "../components/ui/navigation-menu";
import {
Sheet,
SheetContent,
SheetHeader,
SheetTitle,
SheetTrigger,
} from "../components/ui/sheet";
import { buttonVariants } from "./ui/button";
import { Menu } from "lucide-react";
import { ModeToggle } from "./mode-toggle";
import { LogoIcon } from "./Icons";
interface RouteProps {
href: string;
label: string;
}
const routeList: RouteProps[] = [
{
href: "#about",
label: "About",
},
{
href: "#howItWorks",
label: "How it works",
},
{
href: "#team",
label: "Team",
},
{
href: "#faq",
label: "FAQ",
},
];
export const Navbar = () => {
const [isOpen, setIsOpen] = useState<boolean>(false);
return (
<header className="sticky border-b-[1px] top-0 z-40 w-full bg-white dark:border-b-slate-700 dark:bg-background" style={{overflow: "hidden"}}>
<NavigationMenu className="mx-auto">
<NavigationMenuList className="container h-14 px-4 w-screen flex justify-between ">
<NavigationMenuItem className="font-bold flex">
<a href="#" className="ml-2 font-bold text-xl flex">
<LogoIcon />
SkillHub
</a>
</NavigationMenuItem>
{/* mobile */}
<span className="flex md:hidden">
<ModeToggle />
<Sheet open={isOpen} onOpenChange={setIsOpen}>
<SheetTrigger className="px-2">
<Menu
className="flex md:hidden h-5 w-5"
onClick={() => setIsOpen(true)}
>
<span className="sr-only">Menu Icon</span>
</Menu>
</SheetTrigger>
<SheetContent side={"left"}>
<SheetHeader>
<SheetTitle className="font-bold text-xl">
SkillHub
</SheetTitle>
</SheetHeader>
<nav className="flex flex-col justify-center items-center gap-2 mt-4">
{routeList.map(({ href, label }: RouteProps) => (
<a
key={label}
href={href}
onClick={() => setIsOpen(false)}
className={buttonVariants({ variant: "ghost" })}
>
{label}
</a>
))}
<Link
to={"login"}
className={`w-[110px] border ${buttonVariants({
variant: "default",
})}`}
>
Login
</Link>
</nav>
</SheetContent>
</Sheet>
</span>
{/* desktop */}
<nav className="hidden md:flex gap-2">
{routeList.map((route: RouteProps, i) => (
<a
href={route.href}
key={i}
className={`text-[17px] ${buttonVariants({
variant: "ghost",
})}`}
>
{route.label}
</a>
))}
</nav>
<div className="hidden md:flex gap-2">
<Link
to={"login"}
className={`border ${buttonVariants({ variant: "default" })}`}
>
Signup
</Link>
</div>
</NavigationMenuList>
</NavigationMenu>
</header>
);
};
+38
View File
@@ -0,0 +1,38 @@
import { useState, useEffect } from "react";
import { Button } from "./ui/button";
import { ArrowUpToLine } from "lucide-react";
export const ScrollToTop = () => {
const [showTopBtn, setShowTopBtn] = useState(false);
useEffect(() => {
window.addEventListener("scroll", () => {
if (window.scrollY > 400) {
setShowTopBtn(true);
} else {
setShowTopBtn(false);
}
});
}, []);
const goToTop = () => {
window.scroll({
top: 0,
left: 0,
});
};
return (
<>
{showTopBtn && (
<Button
onClick={goToTop}
className="fixed bottom-4 right-4 opacity-90 shadow-md"
size="icon"
>
<ArrowUpToLine className="h-4 w-4" />
</Button>
)}
</>
);
};
+76
View File
@@ -0,0 +1,76 @@
import { Card, CardDescription, CardHeader, CardTitle } from "./ui/card";
import { MagnifierIcon, WalletIcon, ChartIcon } from "./Icons";
import cubeLeg from "../assets/cube-leg.png";
interface ServiceProps {
title: string;
description: string;
icon: JSX.Element;
}
const serviceList: ServiceProps[] = [
{
title: "Code Collaboration",
description:
"Lorem ipsum dolor sit amet consectetur adipisicing elit. Nisi nesciunt est nostrum omnis ab sapiente.",
icon: <ChartIcon />,
},
{
title: "Project Management",
description:
"Lorem ipsum dolor sit amet consectetur adipisicing elit. Nisi nesciunt est nostrum omnis ab sapiente.",
icon: <WalletIcon />,
},
{
title: "Task Automation",
description:
"Lorem ipsum dolor sit amet consectetur adipisicing elit. Nisi nesciunt est nostrum omnis ab sapiente.",
icon: <MagnifierIcon />,
},
];
export const Services = () => {
return (
<section className="container py-24 sm:py-32">
<div className="grid lg:grid-cols-[1fr,1fr] gap-8 place-items-center">
<div>
<h2 className="text-3xl md:text-4xl font-bold">
<span className="bg-gradient-to-b from-primary/60 to-primary text-transparent bg-clip-text">
Client-Centric{" "}
</span>
Services
</h2>
<p className="text-muted-foreground text-xl mt-4 mb-8 ">
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Veritatis
dolor.
</p>
<div className="flex flex-col gap-8">
{serviceList.map(({ icon, title, description }: ServiceProps) => (
<Card key={title}>
<CardHeader className="space-y-1 flex md:flex-row justify-start items-start gap-4">
<div className="mt-1 bg-primary/20 p-1 rounded-2xl">
{icon}
</div>
<div>
<CardTitle>{title}</CardTitle>
<CardDescription className="text-md mt-2">
{description}
</CardDescription>
</div>
</CardHeader>
</Card>
))}
</div>
</div>
<img
src={cubeLeg}
className="w-[300px] md:w-[500px] lg:w-[600px] object-contain"
alt="About services"
/>
</div>
</section>
);
};
+137
View File
@@ -0,0 +1,137 @@
import { buttonVariants } from "../components/ui/button";
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "../components/ui/card";
import { Github } from "lucide-react";
interface TeamProps {
imageUrl: string;
name: string;
position: string;
socialNetworks: SociaNetworkslProps[];
}
interface SociaNetworkslProps {
name: string;
url: string;
}
const teamList: TeamProps[] = [
{
imageUrl: "https://raw.githubusercontent.com/devitq/devitq/main/logo.png",
name: "ITQ",
position: "Backend & Frontend Developer",
socialNetworks: [
{ name: "GitHub", url: "https://github.com/devitq" },
],
},
{
imageUrl: "https://cdn.discordapp.com/avatars/745800190413373472/db4cd19e6d80f9cfa29e09a43ddbcb28",
name: "Pigeon",
position: "Backend Developer",
socialNetworks: [
{ name: "GitHub", url: "https://github.com/FlyingPigeon-py" },
],
},
{
imageUrl: "https://cdn.discordapp.com/avatars/875043365815717888/2a6ddca40c178c5e91a55c52889f8a98",
name: "Timkaoch",
position: "Backend Developer",
socialNetworks: [
{ name: "GitHub", url: "https://github.com/Timur-liceist" },
],
},
{
imageUrl: "https://cdn.discordapp.com/avatars/743444918197944400/6dcfc04c3931fa5c89e9580eb5f7c655",
name: "Data Name ID",
position: "Backend Developer",
socialNetworks: [
{ name: "GitHub", url: "https://github.com/Data-Name-ID" },
],
},
{
imageUrl: "https://cdn.discordapp.com/avatars/545655609005965345/78d2c594eb858d3bb393928a67ef8731",
name: "OMGKawaiiQueli!",
position: "Frontend Developer",
socialNetworks: [
{ name: "GitHub", url: "https://github.com/cu-e" },
],
},
];
export const Team = () => {
const socialIcon = (iconName: string) => {
switch (iconName) {
case "GitHub":
return <Github size="20" />;
}
};
return (
<section
id="team"
className="container py-24 sm:py-32"
>
<h2 className="text-3xl md:text-4xl font-bold">
<span className="bg-gradient-to-b from-primary/60 to-primary text-transparent bg-clip-text">
Our Dedicated{" "}
</span>
Crew
</h2>
<p className="mt-4 mb-10 text-xl text-muted-foreground">
Our team Animulichki contains 5 dedicated web developers
</p>
<div className="grid md:grid-cols-2 lg:grid-cols-4 gap-8 gap-y-10">
{teamList.map(
({ imageUrl, name, position, socialNetworks }: TeamProps) => (
<Card
key={name}
className="bg-muted/50 relative mt-8 flex flex-col justify-center items-center"
>
<CardHeader className="mt-8 flex justify-center items-center pb-2">
<img
src={imageUrl}
alt={`${name} ${position}`}
className="absolute -top-12 rounded-full w-24 h-24 aspect-square object-cover"
/>
<CardTitle className="text-center">{name}</CardTitle>
<CardDescription className="text-primary">
{position}
</CardDescription>
</CardHeader>
<CardContent className="text-center pb-2">
<p></p>
</CardContent>
<CardFooter>
{socialNetworks.map(({ name, url }: SociaNetworkslProps) => (
<div key={name}>
<a
href={url}
target="_blank"
className={buttonVariants({
variant: "ghost",
size: "sm",
})}
>
<span className="sr-only">{name} icon</span>
{socialIcon(name)}
</a>
</div>
))}
</CardFooter>
</Card>
)
)}
</div>
</section>
);
};
+40
View File
@@ -0,0 +1,40 @@
import React, { Component, RefObject } from "react";
import OrgChart from "@balkangraph/orgchart.js";
interface Node {
name: string;
img: string;
// Add more fields if needed
}
interface ChartProps {
nodes: Node[];
}
export default class Chart extends Component<ChartProps> {
private divRef: RefObject<HTMLDivElement>;
private chart: any;
constructor(props: ChartProps) {
super(props);
this.divRef = React.createRef();
}
shouldComponentUpdate() {
return false;
}
componentDidMount() {
this.chart = new OrgChart(this.divRef.current!, {
nodes: this.props.nodes,
nodeBinding: {
field_0: "name",
img_0: "img",
},
});
}
render() {
return <div id="tree" ref={this.divRef}></div>;
}
}
+9 -5
View File
@@ -1,6 +1,10 @@
// export const API_BASE = "http://158.160.56.239:8080/api/" // export const API_BASE = "https://animulichki.ru/api/"
// export const API_BASE = "http://212.22.79.188:9090/api/" //2 сервер // export const API_BASE = "http://212.22.79.188/api/" //2 сервер
export const API_BASE = "http://localhost:8080/api/" //3 сервер export const API_BASE = "http://localhost/api/" //3 сервер
export const API_REG = "auth/signup/"
export const API_CREATE_TOKEN = "auth/login/"
export const API_EVENT = "events/"
export const API_USERS = "users/"
export const API_REG = "registration/"
export const API_CREATE_TOKEN = "token/"
@@ -1,5 +1,4 @@
import { ThemeProvider } from "../../../theme-provider" import { ThemeProvider } from "../../../theme-provider"
import NavigationBar from "../../../widgets/NavigationBar/NavigationBar"
import '../../../../i18n' import '../../../../i18n'
import less from "./General.module.less" import less from "./General.module.less"
import Header from "../../../widgets/Header/Header" import Header from "../../../widgets/Header/Header"
@@ -10,12 +9,9 @@ function General() {
return ( return (
<ThemeProvider defaultTheme="system" storageKey="vite-ui-theme"> <ThemeProvider defaultTheme="system" storageKey="vite-ui-theme">
<Header /> <Header />
<div className={less['page-maket']}> <main className={less["main-content"]}>
<NavigationBar />
<div className={less["main-content"]}>
<Outlet/> <Outlet/>
</div> </main>
</div>
</ThemeProvider> </ThemeProvider>
) )
@@ -0,0 +1,5 @@
.card{
max-width: 800px;
padding: 20px;
margin-bottom: 10px;
}
@@ -0,0 +1,40 @@
import { useTranslation } from "react-i18next";
import { Card, CardHeader, CardTitle, CardContent } from "../../shared/ui/card"
import less from "./PlayerCard.module.less";
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from "../../shared/ui/dialog";
import { Separator } from "../../shared/ui/separator";
const PlayerCard = () =>{
const { t } = useTranslation();
return(
<Card className={`${less["card"]} flex flex-row `}>
<div className="flex flex-col">
<CardHeader className="p-0">
<CardTitle className="p-0">Lorem ipsum</CardTitle>
</CardHeader >
<CardContent className="p-0 mt-2">
<p>{t("skills")}:</p>
<p>{t("viewingProfile")}:</p>
</CardContent>
<Dialog>
<DialogTrigger className="inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 bg-primary text-primary-foreground hover:bg-primary/90 h-9 px-4 py-1">{t("open")}</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>фио</DialogTitle>
<DialogDescription>
<Separator></Separator>
такой то такой то
</DialogDescription>
</DialogHeader>
</DialogContent>
</Dialog>
</div>
</Card>
)
}
export default PlayerCard;
@@ -1,12 +1,11 @@
.card-img{ .card-img{
border: 2px solid #cdcdcd; border: 2px solid #cdcdcd;
border-radius: 8px; border-radius: 8px;
width: 100%; width: 30%;
height: 100%; background: #d9d9d5
background: #d9d9d9;
} }
.card{ .card{
width: 800px; max-width: 800px;
padding: 20px; padding: 20px;
height: 230px; margin-bottom: 10px;
} }
@@ -1,18 +1,23 @@
import { Button } from "../../shared/ui/button";
import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from "../../shared/ui/card" import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from "../../shared/ui/card"
import less from "./TeamsCard.module.less"; import less from "./TeamsCard.module.less";
import { useTranslation } from "react-i18next";
const TeamsCard = () =>{ const TeamsCard = () =>{
const { t } = useTranslation();
return( return(
<Card className={`${less["card"]} flex flex-row`}> <Card className={`${less["card"]} flex flex-row`}>
<div className={less["card-img"]}></div> <div className={less["card-img"]}></div>
<div className="flex flex-col"> <div className="flex flex-col">
<CardHeader > <CardHeader className="p-0 pl-2">
<CardTitle>Lorem ipsum</CardTitle> <CardTitle>Lorem ipsum</CardTitle>
<CardDescription>Lorem ipsum</CardDescription> <CardDescription>Lorem ipsum</CardDescription>
</CardHeader> </CardHeader>
<CardContent> <CardContent className="p-0 pl-2 mt-4">
<p>Lorem ipsum dolor sit amet consectetur. Lorem justo sit nunc commodo nam fames dui ac ullamcorper. Laoreet faucibus semper adipiscing lobortis.</p> <p>Lorem ipsum dolor sit amet consectetur. Lorem justo sit nunc commodo nam fames dui ac ullamcorper. Laoreet faucibus semper adipiscing lobortis.</p>
</CardContent> </CardContent>
<Button className="mt-5 ml-2">{t("respondRequest")}</Button>
</div> </div>
</Card> </Card>
@@ -0,0 +1,16 @@
.card{
max-width: 800px;
padding: 20px;
margin-bottom: 10px;
}
.up{
display: flex;
flex-direction: column;
}
.header{
display: flex;
flex-direction: row;
justify-content:space-between;
padding: 0;
}
@@ -0,0 +1,41 @@
import { useTranslation } from "react-i18next";
import { Button } from "../../shared/ui/button";
import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from "../../shared/ui/card"
import less from "./VacancyCard.module.less";
import { TrashIcon } from "lucide-react";
import { deleteEvent } from "../../pages/AdminEventPage/AdminEventAPI";
interface VacancyCardProms{
title: string;
date: string;
desc: string;
cardId: string;
admin: boolean;
}
const VacancyCard = ({title, date, desc,cardId, admin = false} : VacancyCardProms) =>{
const { t } = useTranslation();
return(
<Card className={`${less["card"]} flex flex-row `}>
<div className="flex flex-col">
<CardHeader className={less["header"]}>
<div className={less["up"]}>
<CardTitle className="p-0">{title}</CardTitle>
<CardDescription>Дата начала: {date}</CardDescription>
</div>
{admin &&(
<Button size="icon" variant="ghost" onClick={() => deleteEvent(cardId)}><TrashIcon/></Button>
)}
</CardHeader>
<CardContent className="p-0 mt-4">
<p>{desc}</p>
</CardContent>
<Button className="mt-2">{t("respondRequest")}</Button>
</div>
</Card>
)
}
export default VacancyCard;
@@ -0,0 +1,90 @@
import React, { useState } from "react";
export const CheckboxTree = ({ data, setGraph }) => {
const [checkedItems, setCheckedItems] = useState({});
const handleCheckboxChange = (itemName, checked) => {
setCheckedItems((prevCheckedItems) => {
let newCheckedItems = { ...prevCheckedItems, [itemName]: checked };
if (checked) {
const parts = itemName.split(".");
parts.pop();
let parent = parts.join(".");
while (parent) {
newCheckedItems = { ...newCheckedItems, [parent]: true };
const parentParts = parent.split(".");
parentParts.pop();
parent = parentParts.join(".");
}
} else {
uncheckChildren(itemName, newCheckedItems);
}
setGraph(getGraph(newCheckedItems));
return newCheckedItems;
});
};
const getGraph = (checkedItems) => {
const graph = {};
for (const itemName in checkedItems) {
if (checkedItems[itemName]) {
const parts = itemName.split(".");
let currentNode = graph;
for (let i = 0; i < parts.length; i++) {
const part = parts[i];
if (!currentNode[part]) {
currentNode[part] = {};
}
currentNode = currentNode[part];
}
}
}
return graph;
};
const uncheckChildren = (parentName, checkedItems) => {
for (const key in checkedItems) {
if (key.startsWith(parentName + ".")) {
checkedItems[key] = false;
if (typeof checkedItems[key] === "object") {
uncheckChildren(key, checkedItems);
}
}
}
};
const renderCheckboxes = (items, prefix = "") => {
const renderedCheckboxes = [];
for (const key in items) {
const itemName = prefix ? `${prefix}.${key}` : key;
renderedCheckboxes.push(
<div key={itemName}>
<input
id={itemName}
type="checkbox"
checked={checkedItems[itemName] || false}
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
onChange={(e) => handleCheckboxChange(itemName, e.target.checked)}
/>
<label htmlFor={itemName}>{key}</label>
</div>
);
if (typeof items[key] === "object") {
renderedCheckboxes.push(
<div key={`${itemName}-children`} style={{ paddingLeft: "20px" }}>
{renderCheckboxes(items[key], itemName)}
</div>
);
}
}
return renderedCheckboxes;
};
return <div>{renderCheckboxes(data)}</div>;
};
@@ -34,6 +34,6 @@
} }
.p{ .p{
font-size: 16px; font-size: 16px;
color: #d3d3d3; color: #595959;
} }
@@ -32,7 +32,8 @@ const UserProfile = () => {
<Card className={less.card}> <Card className={less.card}>
<h1 className={less.h1}>Имя Фамилия</h1> <h1 className={less.h1}>Имя Фамилия</h1>
<Separator /> <Separator />
<p className={less.p}></p> <p>wefqwf</p>
<p className={less.p}>Lorem ipsum dolor sit amet consectetur. Lorem justo sit nunc commodo nam fames dui ac ullamcorper. Laoreet faucibus semper adipiscing lobortis.</p>
</Card> </Card>
</section> </section>
+33 -34
View File
@@ -1,41 +1,40 @@
import { Moon, Sun } from "lucide-react" import { Button } from "../components/ui/button";
import {
import { Button } from "./shared/ui/button" DropdownMenu,
import { useTheme } from "./theme-provider" DropdownMenuContent,
import { useTranslation } from "react-i18next" DropdownMenuItem,
import { MenubarMenu, MenubarTrigger, MenubarContent, MenubarItem, MenubarSeparator, MenubarShortcut } from "./shared/ui/menubar" DropdownMenuTrigger,
import { ResetIcon } from "@radix-ui/react-icons" } from "../components/ui/dropdown-menu";
import { useTheme } from "../components/theme-provider";
import { Moon, Sun } from "lucide-react";
export function ModeToggle() { export function ModeToggle() {
const { setTheme } = useTheme() const { setTheme } = useTheme();
const { t } = useTranslation();
return ( return (
<MenubarMenu> <DropdownMenu>
<MenubarTrigger asChild> <DropdownMenuTrigger asChild>
<Button variant="ghost" size="sm"> <Button
<Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" /> variant="ghost"
<Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" /> size="icon"
className="ghost"
>
<Sun className="h-[1.1rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
<Moon className="absolute h-[1.1rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
<span className="sr-only">Toggle theme</span> <span className="sr-only">Toggle theme</span>
</Button> </Button>
</MenubarTrigger> </DropdownMenuTrigger>
<MenubarContent align="end"> <DropdownMenuContent align="end">
<MenubarItem onClick={() => setTheme("light")}> <DropdownMenuItem onClick={() => setTheme("light")}>
{t("LightTheme")}<MenubarShortcut>L</MenubarShortcut> Light
</MenubarItem> </DropdownMenuItem>
<MenubarItem onClick={() => setTheme("dark")}> <DropdownMenuItem onClick={() => setTheme("dark")}>
{t("DarkTheme")}<MenubarShortcut>D</MenubarShortcut> Dark
</MenubarItem> </DropdownMenuItem>
<MenubarSeparator /> <DropdownMenuItem onClick={() => setTheme("system")}>
<MenubarItem onClick={() => setTheme("system")}> System
{t("SystemTheme")}<MenubarShortcut><ResetIcon /></MenubarShortcut> </DropdownMenuItem>
</MenubarItem> </DropdownMenuContent>
</MenubarContent> </DropdownMenu>
</MenubarMenu> );
)
} }
@@ -0,0 +1,20 @@
.main-admin{
display: flex;
flex-direction: column;
width: 80%;
justify-content: center;
align-items: center;
gap: 50px;
height: 70vh;
}
.full-content{
padding-top: 80px;
}
.card{
max-width: 800px;
padding: 20px;
margin-bottom: 10px;
margin-left: 5px;
}
@@ -0,0 +1,66 @@
import {
ResizableHandle,
ResizablePanel,
ResizablePanelGroup,
} from "../../shared/ui/resizable";
import less from "./Admin.module.less";
import { useTranslation } from "react-i18next";
import CreateTeam from "../../widgets/CreateTeams/CreateTeams";
import { UserList } from "../AdminEventPage/AdminEventAPI";
import { useEffect, useState } from "react";
import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from "../../shared/ui/card"
const AdminPage = () => {
const { t } = useTranslation();
const [players, setPlayerList] = useState<Event[]>([]);
useEffect(() => {
var index = window.location.pathname.indexOf("/dash/admin/") + "/dash/admin/".length;
var result = window.location.pathname.substring(index);
if(Number(result) > 0){
UserList(result)
.then((data) => {
setPlayerList(data);
})
.catch((error) => {
console.error("Возникла ошибка с получением:", error);
});
}
}, []);
return (
<ResizablePanelGroup className={less["full-content"]} direction="horizontal">
<ResizablePanel defaultSize={60} maxSize={60}>
<div className={less["main-admin"]}>
<CreateTeam />
</div>
</ResizablePanel>
<ResizableHandle withHandle />
<ResizablePanel>
<h4>Members: {players.length}</h4>
{players.map((event) => (
<Card className={`${less["card"]} flex flex-row `}>
<div className="flex flex-col">
<CardHeader className="p-0">
<CardTitle className="p-0">{`${event.first_name} | ${event.email}`}</CardTitle>
</CardHeader >
<CardContent className="p-0 mt-2">
<p>{t("skills")}:</p>
<p>{event.bio}</p>
</CardContent>
</div>
</Card>
))}
</ResizablePanel>
</ResizablePanelGroup>
);
};
export default AdminPage;
@@ -0,0 +1,108 @@
import { FormEvent } from "react";
import { API_BASE, API_EVENT, API_USERS } from "../../app/APIurl";
export const submitAddEvent = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
const formData = new FormData(e.currentTarget);
const formProps = Object.fromEntries(formData);
console.log(formProps)
fetch(`${API_BASE}${API_EVENT}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(formProps) ,
})
.then(response => {
console.log(response.status);
if (response.ok) {
console.log('Создан:', response.headers.get('Location'));
return response.json();
} else {
throw new Error('Код ошибки: ' + response.status);
}
})
.then(data => {
console.log('Успешно:', data);
return data
})
.catch(error => {
console.error('Возникла ошибка с созданием:', error);
});
}
export const eventList = () => {
return fetch(`${API_BASE}${API_EVENT}`, {
method: "GET",
headers: {
"Content-Type": "application/json",
},
})
.then(response => {
if (response.ok) {
return response.json();
} else {
throw new Error('Код ошибки: ' + response.status);
}
})
.then(data => {
return data;
})
.catch(error => {
console.error('Возникла ошибка с получением:', error);
});
}
//удалить ивент
export const deleteEvent = (id:string) => {
fetch(`${API_BASE}${API_EVENT}${id}`, {
method: "DELETE",
headers: {
"Content-Type": "application/json",
},
})
.then(response => {
if (response.ok) {
} else {
throw new Error('Код ошибки: ' + response.status);
}
})
.catch(error => {
console.error('Возникла ошибка с удалением:', error);
});
}
//получение списка юзеров
export const UserList = (id:string) => {
return fetch(`${API_BASE}${API_EVENT}${id}/${API_USERS}`, {
method: "GET",
headers: {
"Content-Type": "application/json",
},
})
.then(response => {
console.log(response.status);
if (response.ok) {
console.log('Получил:', response.headers.get('Location'));
return response.json();
} else {
throw new Error('Код ошибки: ' + response.status);
}
})
.then(data => {
console.log('Успешно:', data);
return data
})
.catch(error => {
console.error('Возникла ошибка с получением:', error);
});
}
@@ -0,0 +1,37 @@
.main-admin{
display: flex;
flex-direction: column;
width: 80%;
justify-content: center;
align-items: center;
gap: 50px;
margin-top: 40px;
height: 70vh;
}
.admin-event__page{
display: flex;
}
.cont_1{
width: 50%;
border-right-width: 1px;
height: 100vh;
padding: 20px;
}
.cont_2{
width: 50%;
padding: 20px;
display: flex;
flex-direction: column;
}
.input-form{
display: flex;
flex-direction: column;
gap: 5px;
}
.liner-block{
display: flex;
align-items: center;
}
@@ -0,0 +1,57 @@
import { Input } from "../../shared/ui/input";
import VacancyCard from "../../entities/VacancyCard/VacancyCard";
import less from "./AdminEventPage.module.less"
import { useTranslation } from "react-i18next";
import { Button } from "../../shared/ui/button";
import { Textarea } from "../../shared/ui/textarea";
import { eventList, submitAddEvent } from "./AdminEventAPI";
import { Switch } from "../../shared/ui/switch";
import { Label } from "../../shared/ui/label";
import { useEffect, useState } from "react";
const AdminEventPage = () => {
const { t } = useTranslation();
const [events, setEvents] = useState<Event[]>([]);
useEffect(() => {
eventList().then((data) => {
setEvents(data)
}).catch(error => {
console.error('Возникла ошибка с получением:', error)
})
}, []);
return (
<div className={less["admin-event__page"]}>
<div className={less["cont_1"]}>
<form className={less["input-form"]} onSubmit={(event) => submitAddEvent(event)}>
<h1 className={less["title-titleform"]}>{t("createEvent")}</h1>
<Input type="text" name="title" placeholder="Event name" />
<Input type="date" name="start_date" placeholder="Start Date" />
<Input type="date" name="end_date" placeholder="End Date" />
<Textarea name="description" placeholder="About Event" />
<div className={less["liner-block"]}>
<Switch name="is_online" />
<Label htmlFor="airplane-mode">Онлайн мероприятие</Label>
</div>
<Button>{t("createEvent")}</Button>
</form>
</div>
<div className={less["cont_2"]}>
{events.map((event) => (
<VacancyCard title={event.title} date={event.start_date} desc={event.description} cardId={event.id} admin={true}></VacancyCard>
))}
</div>
</div>
)
}
export default AdminEventPage
@@ -12,7 +12,7 @@
font-family: "Arial Black"; font-family: "Arial Black";
margin-top: 200px; margin-top: 200px;
margin-left: 20px; margin-left: 20px;
font-size: 150px; font-size: 120px;
line-height: 100%; line-height: 100%;
text-transform: uppercase; text-transform: uppercase;
@@ -21,6 +21,67 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
width: 500px;
margin: 0 auto; margin: 0 auto;
}
.desc-text{
margin-top: 10px;
margin-bottom: 2px;
text-align: center;
word-wrap: break-word;
}
@media (max-width: 910px) {
.landing{
font-family: "Arial Black";
margin-top: 100px;
margin-left: 20px;
font-size: 100px;
line-height: 100%;
text-transform: uppercase;
}
}
@media (max-width: 760px) {
.landing{
font-family: "Arial Black";
margin-top: 100px;
margin-left: 20px;
font-size: 80px;
line-height: 100%;
text-transform: uppercase;
}
}
@media (max-width: 520px) {
.landing{
font-family: "Arial Black";
margin-top: 100px;
margin-left: 20px;
font-size: 60px;
line-height: 100%;
text-transform: uppercase;
}
.info-block{
display: flex;
position:absolute;
bottom: 0px;
padding: 5px;
padding-bottom: 15px;
flex-direction: column;
align-items: center;
margin: 0 auto;
background-color: rgba(88, 88, 88, 0.4);
}
}
@media (max-width: 400px) {
.landing{
font-family: "Arial Black";
margin-top: 100px;
margin-left: 20px;
font-size: 40px;
line-height: 100%;
text-transform: uppercase;
}
} }
@@ -1,21 +1,27 @@
import less from "./Landing.module.less" import { About } from "../../About";
import '../../../i18n' import { FAQ } from "../../FAQ";
import { Button } from "../../shared/ui/button" import { Footer } from "../../Footer";
import { Label } from "@radix-ui/react-menubar" import { Hero } from "../../Hero";
import { useTranslation } from "react-i18next"; import { HowItWorks } from "../../HowItWorks";
import { Navbar } from "../../Navbar";
import { ScrollToTop } from "../../ScrollToTop";
import { Team } from "../../Team";
import "../../../App.css";
import { ThemeProvider } from "../../theme-provider.tsx";
function Landing() { function Landing() {
const { t } = useTranslation();
return ( return (
<><div className={less.block}></div> <ThemeProvider>
<h1 className={less.landing}>{t("landingLogo")}</h1> <Navbar />
<div className={less["info-block"]}> <Hero />
<Label className="mt-10 mb-1">Lorem ipsum dolor sit amet consectetur. Tincidunt nunc duis interdum feugiat viverra tellus eu amet fermentum. Metus nulla lacinia egestas scelerisque porta urna et massa. Id ut vel aliquet lorem velit. Blandit interdum enim suspendisse non at sem nulla diam ullamcorper.</Label> <About />
<Button variant="outline">{t("buttonGoTOReg")}</Button> <HowItWorks />
</div> <Team />
</> <FAQ />
) <Footer />
<ScrollToTop />
</ThemeProvider>
);
} }
export default Landing export default Landing;
@@ -1,6 +1,66 @@
.divv{ .divv{
margin: 0; margin: 0;
} }
.novis{
opacity: 0;
visibility: hidden;
}
.general-content{ .general-content{
margin-left: 20px; margin-left: 20px;
} display: flex;
}
.general-left{
width: 50%;
padding: 10px;
padding-top: 80px;
border-right-width: 1px;
}
.general-right{
padding-top: 80px;
margin-left: 20px;
width: 30%;
}
.input-form{
width: 100%;
display: flex;
flex-direction: column;
gap: 5px;
width: 80%;
margin-bottom: 40px;
}
.input-item{
width: 80%;
}
.title-form{
font-size: 30px;
}
.card{
max-width: 800px;
padding: 20px;
margin-bottom: 10px;
}
.up{
display: flex;
flex-direction: column;
}
.header{
display: flex;
flex-direction: row;
justify-content:space-between;
padding: 0;
}
.model-content{
display: flex;
flex-direction: column;
justify-content:center;
}
@media (max-width: 820px) {
.general-left{
width: 100%;
}
}
+122 -12
View File
@@ -1,14 +1,124 @@
import SearchBar from "../../features/SearchBar/SearchBar"; import less from "./Main.module.less";
import TeamsCard from "../../entities/TeamsCard/TeamsCard"; import { useTranslation } from "react-i18next";
import less from "./Main.module.less" import { Input } from "../../shared/ui/input";
import { submitRegister } from "../../widgets/Header/AuthAPI";
import { Button } from "../../shared/ui/button";
import { Textarea } from "../../shared/ui/textarea";
import { Link, useNavigate } from "react-router-dom";
import { useEffect, useState } from "react";
import { deleteEvent, eventList } from "../AdminEventPage/AdminEventAPI";
import { CheckboxTree } from "../../features/Skills/Skills";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "../../ui/card";
import { TrashIcon } from "lucide-react";
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "../../shared/ui/dialog";
const Main = () => { const Main = () => {
return ( const { t } = useTranslation();
<><div><SearchBar title="Вакансии" /> const navigate = useNavigate();
</div><div className={less["general-content"]}>
<TeamsCard /> const [graph, setGraph] = useState({});
</div></> const [events, setEvents] = useState<Event[]>([]);
)
} useEffect(() => {
export default Main; eventList()
.then((data) => {
setEvents(data);
})
.catch((error) => {
console.error("Возникла ошибка с получением:", error);
});
}, []);
return (
<div className={less["general-content"]}>
<div className={less["general-left"]}>
{events.map((event) => (
<Card className={`${less["card"]} flex flex-row `}>
<div className="flex flex-col">
<CardHeader className={less["header"]}>
<div className={less["up"]}>
<CardTitle className="p-0">{event.title}</CardTitle>
<CardDescription>
Start Date: {event.start_date}
</CardDescription>
</div>
{false && (
<Button
size="icon"
variant="ghost"
onClick={() => deleteEvent(event.id)}
>
<TrashIcon />
</Button>
)}
</CardHeader>
<CardContent className="p-0 mt-4">
<p>{event.description}</p>
</CardContent>
<Dialog style={{ height: "fixed" }}>
<DialogTrigger className="inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 bg-primary text-primary-foreground hover:bg-primary/90 h-9 px-4 py-2">
{t("respondRequest")}
</DialogTrigger>
<DialogContent className={"lg:max-w-screen-lg overflow-y-scroll max-h-screen"}>
<DialogHeader>
<DialogTitle>
<h1 className={less["title-form"]}>{t("entrance")}</h1>
</DialogTitle>
</DialogHeader>
<form
className={less["input-form"]}
onSubmit={(event) => submitRegister(event, navigate, graph)}
>
<div className={less["novis"]}>
<Input
type="text"
name="event"
value={event.id}
placeholder="Event"
/>
</div>
<Input
type="text"
name="first_name"
placeholder="First name"
/>
<Input
type="text"
name="last_name"
placeholder="Last name"
/>
<Input type="date" name="birth_date" placeholder="Date" />
<Input type="email" name="email" placeholder="Email" />
<Textarea name="bio" placeholder="About" />
<CheckboxTree data={event.tree} setGraph={setGraph} />
<Button>Signup</Button>
</form>
</DialogContent>
</Dialog>
</div>
</Card>
))}
<Button variant="link" asChild>
<Link to={"/dash/skill-tree"}>{t("iorganizer")}</Link>
</Button>
</div>
<div className={less["general-right"] + " shadow"}></div>
</div>
);
};
export default Main;
@@ -1,7 +1,7 @@
import TeamCard from "../../widgets/TeamCard/TeamCard"; import TeamCard from "../../widgets/TeamInfoBlock/TeamInfoBlock";
import UserProfile from "../../features/UserProfile/UserProfile"; import UserProfile from "../../features/UserProfile/UserProfile";
import less from "./MyTeams.module.less" import less from "./MyTeams.module.less"
import CreateTeam from "../../widgets/CreateTeam/CreateTeam"; import CreateTeam from "../../widgets/CreateTeams/CreateTeams";
const MyTeams = () => { const MyTeams = () => {
@@ -0,0 +1,42 @@
.general{
display: flex;
flex-direction: row;
padding-top: 80px;
}
.left{
width: 50%;
padding: 20px;
padding-top: 0;
}
.right{
width: 50%;
}
.card{
margin: 10px;
padding: 10px;
}
.input-form{
display: flex;
flex-direction: column;
gap: 8px;
}
.title{
padding: 0;
}
.up{
display: flex;
flex-direction: column;
}
.header{
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
padding: 0;
}
.h2{
font-size: 24px;
font-weight: 600;
}

Some files were not shown because too many files have changed in this diff Show More