diff --git a/backend/project/api/teams/migrations/0001_initial.py b/backend/project/api/teams/migrations/0001_initial.py
new file mode 100644
index 0000000..47871cd
--- /dev/null
+++ b/backend/project/api/teams/migrations/0001_initial.py
@@ -0,0 +1,45 @@
+# Generated by Django 4.2.11 on 2024-03-31 19:06
+
+from django.conf import settings
+import django.core.validators
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ('users', '0002_rename_technologies_user_skills'),
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ]
+
+ operations = [
+ 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, verbose_name='название вакансии')),
+ ('start_date', models.DateField(blank=True, null=True, verbose_name='дата начала диапазона возраста участников')),
+ ('end_date', models.DateField(blank=True, null=True, verbose_name='дата конец диапазона возраста участников')),
+ ('skills', models.ManyToManyField(blank=True, to='users.skill', verbose_name='Технологии')),
+ ('specialization', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='users.specialization', verbose_name='специализация')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Team',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('description', models.TextField(verbose_name='описание команды')),
+ ('name', models.CharField(max_length=255, verbose_name='название команды')),
+ ('avatar', models.ImageField(blank=True, upload_to='teams_avatars', verbose_name='аватарка')),
+ ('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='город')),
+ ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='teams', to=settings.AUTH_USER_MODEL)),
+ ('members', models.ManyToManyField(to=settings.AUTH_USER_MODEL, verbose_name='участники')),
+ ('vacancies', models.ManyToManyField(to='teams.vacancy', verbose_name='вакансии')),
+ ],
+ ),
+ ]
diff --git a/backend/project/api/teams/serializer.py b/backend/project/api/teams/serializers.py
similarity index 100%
rename from backend/project/api/teams/serializer.py
rename to backend/project/api/teams/serializers.py
diff --git a/backend/project/config/settings.py b/backend/project/config/settings.py
index 346389d..e0255e4 100755
--- a/backend/project/config/settings.py
+++ b/backend/project/config/settings.py
@@ -44,6 +44,7 @@ INSTALLED_APPS = [
# Third-party apps
"rest_framework",
"rest_framework_simplejwt",
+ "corsheaders",
"drf_yasg",
# Developed apps
"api.ping.apps.PingConfig",
@@ -58,6 +59,8 @@ MIDDLEWARE = [
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
+ "corsheaders.middleware.CorsMiddleware",
+ "django.middleware.common.CommonMiddleware",
]
ROOT_URLCONF = "config.urls"
diff --git a/backend/project/notifications/migrations/0002_alter_notification_content.py b/backend/project/notifications/migrations/0002_alter_notification_content.py
new file mode 100644
index 0000000..0bdbb42
--- /dev/null
+++ b/backend/project/notifications/migrations/0002_alter_notification_content.py
@@ -0,0 +1,18 @@
+# Generated by Django 4.2.11 on 2024-03-31 19:06
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('notifications', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='notification',
+ name='content',
+ field=models.TextField(verbose_name='содержание'),
+ ),
+ ]
diff --git a/backend/requirements/lint.txt b/backend/requirements/lint.txt
new file mode 100644
index 0000000..40b7f22
--- /dev/null
+++ b/backend/requirements/lint.txt
@@ -0,0 +1,2 @@
+sort-requirements
+ruff
diff --git a/backend/requirements/prod.txt b/backend/requirements/prod.txt
index 2e3883a..27510b8 100644
--- a/backend/requirements/prod.txt
+++ b/backend/requirements/prod.txt
@@ -8,5 +8,6 @@ djangorestframework-simplejwt==5.3.1
django-filter==24.2
Pillow==10.2.0
drf-yasg==1.21.7
+django-cors-headers
setuptools
bcrypt==4.1.2
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 74ccdf7..6f32b45 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -1,10 +1,12 @@
{
+ "name": "skill-hub",
"name": "skill-hub",
"version": "0.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
+ "name": "skill-hub",
"name": "skill-hub",
"version": "0.0.0",
"dependencies": {
@@ -19,6 +21,8 @@
"@radix-ui/react-tabs": "^1.0.4",
"@vitejs/plugin-react-swc": "^3.5.0",
"autoprefixer": "^10.4.19",
+ "@vitejs/plugin-react-swc": "^3.5.0",
+ "autoprefixer": "^10.4.19",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.0",
"cn-decorator": "^2.1.0",
@@ -26,8 +30,10 @@
"eslint-plugin-react": "^7.34.1",
"i18next": "^23.10.1",
"less": "^4.2.0",
+ "less": "^4.2.0",
"lucide-react": "^0.363.0",
"postcss": "^8.4.38",
+ "postcss": "^8.4.38",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hook-form": "^7.51.2",
@@ -36,9 +42,12 @@
"react-router-dom": "^6.22.3",
"tailwind-merge": "^2.2.2",
"tailwindcss": "^3.4.3",
+ "tailwindcss": "^3.4.3",
"tailwindcss-animate": "^1.0.7",
"typescript": "^5.2.2",
"vite": "^5.2.0",
+ "typescript": "^5.2.2",
+ "vite": "^5.2.0",
"zod": "^3.22.4"
},
"devDependencies": {
@@ -54,6 +63,7 @@
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.6",
"prettier": "^3.2.5"
+ "prettier": "^3.2.5"
}
},
"node_modules/@aashutoshrathi/word-wrap": {
@@ -1792,6 +1802,7 @@
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz",
"integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ=="
+ "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ=="
},
"node_modules/@swc/types": {
"version": "0.1.6",
@@ -1805,6 +1816,7 @@
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="
+ "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="
},
"node_modules/@types/json-schema": {
"version": "7.0.15",
@@ -1824,6 +1836,7 @@
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.30.tgz",
"integrity": "sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==",
"devOptional": true,
+ "devOptional": true,
"dependencies": {
"undici-types": "~5.26.4"
}
@@ -2625,6 +2638,11 @@
"resolved": "https://registry.npmjs.org/cross/-/cross-1.0.0.tgz",
"integrity": "sha512-p6hXbCnjuIB4bhKWFeztQd7VwffgQP9zOBzUoiA8Lvi01RzQY0e7PbPFU/uqVPTM2stY7uCpVck1UTPpxhinMQ=="
},
+ "node_modules/cross": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/cross/-/cross-1.0.0.tgz",
+ "integrity": "sha512-p6hXbCnjuIB4bhKWFeztQd7VwffgQP9zOBzUoiA8Lvi01RzQY0e7PbPFU/uqVPTM2stY7uCpVck1UTPpxhinMQ=="
+ },
"node_modules/cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@@ -2811,6 +2829,7 @@
"version": "1.4.721",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.721.tgz",
"integrity": "sha512-k1x2r6foI8iJOp+1qTxbbrrWMsOiHkzGBYwYigaq+apO1FSqtn44KTo3Sy69qt7CRr7149zTcsDvH7MUKsOuIQ=="
+ "integrity": "sha512-k1x2r6foI8iJOp+1qTxbbrrWMsOiHkzGBYwYigaq+apO1FSqtn44KTo3Sy69qt7CRr7149zTcsDvH7MUKsOuIQ=="
},
"node_modules/emoji-regex": {
"version": "9.2.2",
@@ -5020,6 +5039,7 @@
"version": "2.0.14",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz",
"integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw=="
+ "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw=="
},
"node_modules/normalize-path": {
"version": "3.0.0",
@@ -6586,6 +6606,7 @@
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
"devOptional": true
+ "devOptional": true
},
"node_modules/update-browserslist-db": {
"version": "1.0.13",
diff --git a/frontend/src/components/app/APIurl.ts b/frontend/src/components/app/APIurl.ts
new file mode 100644
index 0000000..f9dc4f1
--- /dev/null
+++ b/frontend/src/components/app/APIurl.ts
@@ -0,0 +1,6 @@
+// export const API_BASE = "http://158.160.56.239:8080/api/"
+// export const API_BASE = "http://212.22.79.188:9090/api/" //2 сервер
+export const API_BASE = "http://localhost:8080/api/" //3 сервер
+
+export const API_REG = "registration/"
+export const API_CREATE_TOKEN = "token/"
diff --git a/frontend/src/components/features/SearchBar/SearchBar.module.less b/frontend/src/components/features/SearchBar/SearchBar.module.less
index 3c56a78..0fbdfa4 100644
--- a/frontend/src/components/features/SearchBar/SearchBar.module.less
+++ b/frontend/src/components/features/SearchBar/SearchBar.module.less
@@ -13,7 +13,6 @@
font-weight: 900;
font-size: 16px;
line-height: 100%;
-color: #000;
}
.input-search{
border: 0;
diff --git a/frontend/src/components/features/UserProfile/UserProfile.module.less b/frontend/src/components/features/UserProfile/UserProfile.module.less
new file mode 100644
index 0000000..8e5a755
--- /dev/null
+++ b/frontend/src/components/features/UserProfile/UserProfile.module.less
@@ -0,0 +1,39 @@
+@icon-size: 256px;
+
+.user-icon{
+ margin: 20px;
+
+ width: @icon-size;
+ height: @icon-size;
+
+ border-radius: 200px;
+
+ background-color: #222222;
+ border: 2px #3c3c3c solid;
+}
+.username{
+
+ color: #828282;
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
+ font-weight: lighter;
+ font-weight: 200;
+ font-size: 24px;
+}
+.card{
+ margin: 20px;
+ padding: 10px;
+ width: calc(100% - 20px);
+
+}
+.info-line{
+ display: flex;
+}
+
+.h1{
+ font-size: 36px;
+}
+.p{
+ font-size: 16px;
+ color: #d3d3d3;
+}
+
diff --git a/frontend/src/components/features/UserProfile/UserProfile.tsx b/frontend/src/components/features/UserProfile/UserProfile.tsx
new file mode 100644
index 0000000..5a92879
--- /dev/null
+++ b/frontend/src/components/features/UserProfile/UserProfile.tsx
@@ -0,0 +1,41 @@
+
+import { Separator } from "../../shared/ui/separator";
+import { Card } from "../../shared/ui/card";
+import less from "./UserProfile.module.less"
+import { PanelRightDashedIcon, Pointer, PointerOff } from "lucide-react";
+
+const UserProfile = () => {
+ return (
+ Город Москва Город Москва telegram @wolfusername
+ Имя Фамилия
+
My teams
+ <> +Город
Москва
Город
Москва
18+