feat: add auth modal
|
@ -15,6 +15,7 @@
|
|||
|
||||
# production
|
||||
/dist
|
||||
/build
|
||||
|
||||
# ide
|
||||
/.idea
|
||||
|
|
|
@ -30,6 +30,37 @@
|
|||
},
|
||||
"Messages": {
|
||||
"title": "Messages"
|
||||
},
|
||||
"Settings": {
|
||||
"title": "Profile Settings",
|
||||
"photo-desc": "Add a real photo, as a person's face is always more credible.",
|
||||
"name": "Name",
|
||||
"surname": "Surname",
|
||||
"birthday": "Date of Birth",
|
||||
"email": "E-mail",
|
||||
"change-password": "Change Password",
|
||||
"save": "Save",
|
||||
"old-password": "Old Password",
|
||||
"new-password": "New Password",
|
||||
"confirm-password": "Confirm Password"
|
||||
},
|
||||
"LegalInformation": {
|
||||
"title": "Legal Information"
|
||||
},
|
||||
"Support": {
|
||||
"title": "Help & Support"
|
||||
},
|
||||
"Notifications": {
|
||||
"title": "Notifications",
|
||||
"read": "Read",
|
||||
"delete": "Delete"
|
||||
},
|
||||
"Sessions": {
|
||||
"upcoming-sessions": "Upcoming Sessions",
|
||||
"sessions-requested": "Sessions Requested",
|
||||
"recent-sessions": "Recent Sessions",
|
||||
"topic": "Topic",
|
||||
"day-start": "Day start"
|
||||
}
|
||||
},
|
||||
"Footer": {
|
||||
|
|
|
@ -31,6 +31,37 @@
|
|||
},
|
||||
"Messages": {
|
||||
"title": "Messages"
|
||||
},
|
||||
"Settings": {
|
||||
"title": "Profile Settings",
|
||||
"photo-desc": "Add a real photo, as a person's face is always more credible.",
|
||||
"name": "Name",
|
||||
"surname": "Surname",
|
||||
"birthday": "Date of Birth",
|
||||
"email": "E-mail",
|
||||
"change-password": "Change Password",
|
||||
"save": "Save",
|
||||
"old-password": "Old Password",
|
||||
"new-password": "New Password",
|
||||
"confirm-password": "Confirm Password"
|
||||
},
|
||||
"LegalInformation": {
|
||||
"title": "Legal Information"
|
||||
},
|
||||
"Support": {
|
||||
"title": "Help & Support"
|
||||
},
|
||||
"Notifications": {
|
||||
"title": "Notifications",
|
||||
"read": "Read",
|
||||
"delete": "Delete"
|
||||
},
|
||||
"Sessions": {
|
||||
"upcoming-sessions": "Upcoming Sessions",
|
||||
"sessions-requested": "Sessions Requested",
|
||||
"recent-sessions": "Recent Sessions",
|
||||
"topic": "Topic",
|
||||
"day-start": "Day start"
|
||||
}
|
||||
},
|
||||
"Footer": {
|
||||
|
|
|
@ -30,6 +30,37 @@
|
|||
},
|
||||
"Messages": {
|
||||
"title": "Messages"
|
||||
},
|
||||
"Settings": {
|
||||
"title": "Profile Settings",
|
||||
"photo-desc": "Add a real photo, as a person's face is always more credible.",
|
||||
"name": "Name",
|
||||
"surname": "Surname",
|
||||
"birthday": "Date of Birth",
|
||||
"email": "E-mail",
|
||||
"change-password": "Change Password",
|
||||
"save": "Save",
|
||||
"old-password": "Old Password",
|
||||
"new-password": "New Password",
|
||||
"confirm-password": "Confirm Password"
|
||||
},
|
||||
"LegalInformation": {
|
||||
"title": "Legal Information"
|
||||
},
|
||||
"Support": {
|
||||
"title": "Help & Support"
|
||||
},
|
||||
"Notifications": {
|
||||
"title": "Notifications",
|
||||
"read": "Read",
|
||||
"delete": "Delete"
|
||||
},
|
||||
"Sessions": {
|
||||
"upcoming-sessions": "Upcoming Sessions",
|
||||
"sessions-requested": "Sessions Requested",
|
||||
"recent-sessions": "Recent Sessions",
|
||||
"topic": "Topic",
|
||||
"day-start": "Day start"
|
||||
}
|
||||
},
|
||||
"Footer": {
|
||||
|
|
|
@ -30,6 +30,37 @@
|
|||
},
|
||||
"Messages": {
|
||||
"title": "Messages"
|
||||
},
|
||||
"Settings": {
|
||||
"title": "Profile Settings",
|
||||
"photo-desc": "Add a real photo, as a person's face is always more credible.",
|
||||
"name": "Name",
|
||||
"surname": "Surname",
|
||||
"birthday": "Date of Birth",
|
||||
"email": "E-mail",
|
||||
"change-password": "Change Password",
|
||||
"save": "Save",
|
||||
"old-password": "Old Password",
|
||||
"new-password": "New Password",
|
||||
"confirm-password": "Confirm Password"
|
||||
},
|
||||
"LegalInformation": {
|
||||
"title": "Legal Information"
|
||||
},
|
||||
"Support": {
|
||||
"title": "Help & Support"
|
||||
},
|
||||
"Notifications": {
|
||||
"title": "Notifications",
|
||||
"read": "Read",
|
||||
"delete": "Delete"
|
||||
},
|
||||
"Sessions": {
|
||||
"upcoming-sessions": "Upcoming Sessions",
|
||||
"sessions-requested": "Sessions Requested",
|
||||
"recent-sessions": "Recent Sessions",
|
||||
"topic": "Topic",
|
||||
"day-start": "Day start"
|
||||
}
|
||||
},
|
||||
"Footer": {
|
||||
|
|
|
@ -30,6 +30,37 @@
|
|||
},
|
||||
"Messages": {
|
||||
"title": "Messages"
|
||||
},
|
||||
"Settings": {
|
||||
"title": "Profile Settings",
|
||||
"photo-desc": "Add a real photo, as a person's face is always more credible.",
|
||||
"name": "Name",
|
||||
"surname": "Surname",
|
||||
"birthday": "Date of Birth",
|
||||
"email": "E-mail",
|
||||
"change-password": "Change Password",
|
||||
"save": "Save",
|
||||
"old-password": "Old Password",
|
||||
"new-password": "New Password",
|
||||
"confirm-password": "Confirm Password"
|
||||
},
|
||||
"LegalInformation": {
|
||||
"title": "Legal Information"
|
||||
},
|
||||
"Support": {
|
||||
"title": "Help & Support"
|
||||
},
|
||||
"Notifications": {
|
||||
"title": "Notifications",
|
||||
"read": "Read",
|
||||
"delete": "Delete"
|
||||
},
|
||||
"Sessions": {
|
||||
"upcoming-sessions": "Upcoming Sessions",
|
||||
"sessions-requested": "Sessions Requested",
|
||||
"recent-sessions": "Recent Sessions",
|
||||
"topic": "Topic",
|
||||
"day-start": "Day start"
|
||||
}
|
||||
},
|
||||
"Footer": {
|
||||
|
|
|
@ -23,13 +23,44 @@
|
|||
"work-with-us": "Работать с нами"
|
||||
},
|
||||
"WorkWithUs": {
|
||||
"title": "Become a BBuddy Expert",
|
||||
"title": "Стань BBuddy экспертом",
|
||||
"insert-info": "Insert your personal information to start your journey as a BBuddy Expert",
|
||||
"start": "Get Started",
|
||||
"start": "Начать",
|
||||
"base-text": "Your info can either be added or amended at anytime"
|
||||
},
|
||||
"Messages": {
|
||||
"title": "Сообщения"
|
||||
},
|
||||
"Settings": {
|
||||
"title": "Настройки пользователя",
|
||||
"photo-desc": "Добавьте реальное фото, это вызывает больше доверия",
|
||||
"name": "Имя",
|
||||
"surname": "Фамилия",
|
||||
"birthday": "Дата рождения",
|
||||
"email": "E-mail",
|
||||
"change-password": "Изменить пароль",
|
||||
"save": "Сохранить изменения",
|
||||
"old-password": "Старый пароль",
|
||||
"new-password": "Новый пароль",
|
||||
"confirm-password": "Подтверждение пароля"
|
||||
},
|
||||
"LegalInformation": {
|
||||
"title": "Legal Information"
|
||||
},
|
||||
"Support": {
|
||||
"title": "Помощь и поддержка"
|
||||
},
|
||||
"Notifications": {
|
||||
"title": "Оповещения",
|
||||
"read": "Смотреть",
|
||||
"delete": "Удалить"
|
||||
},
|
||||
"Sessions": {
|
||||
"upcoming-sessions": "Upcoming Sessions",
|
||||
"sessions-requested": "Sessions Requested",
|
||||
"recent-sessions": "Recent Sessions",
|
||||
"topic": "Тема",
|
||||
"day-start": "Дата начала"
|
||||
}
|
||||
},
|
||||
"Footer": {
|
||||
|
|
|
@ -14,9 +14,27 @@ const nextConfig = {
|
|||
sassOptions: {
|
||||
includePaths: [path.join(__dirname, 'styles')],
|
||||
},
|
||||
images: {
|
||||
unoptimized: true
|
||||
},
|
||||
experimental: {
|
||||
taint: true,
|
||||
typedRoutes: true
|
||||
},
|
||||
output: 'export',
|
||||
cleanDistDir: true,
|
||||
distDir: 'dist'
|
||||
distDir: 'dist',
|
||||
poweredByHeader: false,
|
||||
productionBrowserSourceMaps: true,
|
||||
trailingSlash: true
|
||||
// redirects: async () => {
|
||||
// return [
|
||||
// {
|
||||
// source: '/en/',
|
||||
// destination: '/en.html',
|
||||
// permanent: true
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
};
|
||||
|
||||
module.exports = withNextIntl(nextConfig);
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
"@ant-design/cssinjs": "^1.18.1",
|
||||
"@ant-design/icons": "^5.2.6",
|
||||
"antd": "^5.12.1",
|
||||
"axios": "^1.6.5",
|
||||
"next": "14.0.3",
|
||||
"next-intl": "^3.3.1",
|
||||
"react": "^18",
|
||||
|
@ -1123,6 +1124,11 @@
|
|||
"has-symbols": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
|
||||
},
|
||||
"node_modules/autoprefixer": {
|
||||
"version": "10.4.16",
|
||||
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.16.tgz",
|
||||
|
@ -1181,6 +1187,16 @@
|
|||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.6.5",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.5.tgz",
|
||||
"integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.15.4",
|
||||
"form-data": "^4.0.0",
|
||||
"proxy-from-env": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/axobject-query": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz",
|
||||
|
@ -1403,6 +1419,17 @@
|
|||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"dependencies": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/compute-scroll-into-view": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.1.0.tgz",
|
||||
|
@ -1524,6 +1551,14 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dequal": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
|
||||
|
@ -2243,6 +2278,25 @@
|
|||
"integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.15.4",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz",
|
||||
"integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||
}
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"debug": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/for-each": {
|
||||
"version": "0.3.3",
|
||||
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
|
||||
|
@ -2252,6 +2306,19 @@
|
|||
"is-callable": "^1.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
|
||||
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"mime-types": "^2.1.12"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/fraction.js": {
|
||||
"version": "4.3.7",
|
||||
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz",
|
||||
|
@ -3180,6 +3247,25 @@
|
|||
"node": ">=8.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"dependencies": {
|
||||
"mime-db": "1.52.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
|
@ -3624,6 +3710,11 @@
|
|||
"react-is": "^16.13.1"
|
||||
}
|
||||
},
|
||||
"node_modules/proxy-from-env": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
|
||||
},
|
||||
"node_modules/punycode": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||
|
@ -5938,6 +6029,11 @@
|
|||
"has-symbols": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
|
||||
},
|
||||
"autoprefixer": {
|
||||
"version": "10.4.16",
|
||||
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.16.tgz",
|
||||
|
@ -5964,6 +6060,16 @@
|
|||
"integrity": "sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==",
|
||||
"dev": true
|
||||
},
|
||||
"axios": {
|
||||
"version": "1.6.5",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.5.tgz",
|
||||
"integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==",
|
||||
"requires": {
|
||||
"follow-redirects": "^1.15.4",
|
||||
"form-data": "^4.0.0",
|
||||
"proxy-from-env": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"axobject-query": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz",
|
||||
|
@ -6113,6 +6219,14 @@
|
|||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true
|
||||
},
|
||||
"combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"requires": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"compute-scroll-into-view": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.1.0.tgz",
|
||||
|
@ -6211,6 +6325,11 @@
|
|||
"object-keys": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
|
||||
},
|
||||
"dequal": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
|
||||
|
@ -6776,6 +6895,11 @@
|
|||
"integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==",
|
||||
"dev": true
|
||||
},
|
||||
"follow-redirects": {
|
||||
"version": "1.15.4",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz",
|
||||
"integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw=="
|
||||
},
|
||||
"for-each": {
|
||||
"version": "0.3.3",
|
||||
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
|
||||
|
@ -6785,6 +6909,16 @@
|
|||
"is-callable": "^1.1.3"
|
||||
}
|
||||
},
|
||||
"form-data": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
|
||||
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
|
||||
"requires": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"mime-types": "^2.1.12"
|
||||
}
|
||||
},
|
||||
"fraction.js": {
|
||||
"version": "4.3.7",
|
||||
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz",
|
||||
|
@ -7458,6 +7592,19 @@
|
|||
"picomatch": "^2.3.1"
|
||||
}
|
||||
},
|
||||
"mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"requires": {
|
||||
"mime-db": "1.52.0"
|
||||
}
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
|
@ -7754,6 +7901,11 @@
|
|||
"react-is": "^16.13.1"
|
||||
}
|
||||
},
|
||||
"proxy-from-env": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
|
||||
},
|
||||
"punycode": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"dev": "next dev -p 4200",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint"
|
||||
|
@ -12,6 +12,7 @@
|
|||
"@ant-design/cssinjs": "^1.18.1",
|
||||
"@ant-design/icons": "^5.2.6",
|
||||
"antd": "^5.12.1",
|
||||
"axios": "^1.6.5",
|
||||
"next": "14.0.3",
|
||||
"next-intl": "^3.3.1",
|
||||
"react": "^18",
|
||||
|
|
After Width: | Height: | Size: 733 B |
After Width: | Height: | Size: 855 B |
After Width: | Height: | Size: 1.5 KiB |
|
@ -0,0 +1,11 @@
|
|||
<svg width="192" height="60" viewBox="0 0 192 60" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M37.0913 31.7816V13.8849C35.9805 13.613 34.829 13.477 33.6233 13.477C32.7022 13.477 31.9029 13.5314 31.1849 13.6402L31.2391 26.3147C34.1788 26.4371 36.1431 28.9121 36.1431 31.7816C36.1431 34.719 34.0839 37.2621 31.0223 37.2621C27.893 37.2621 25.8339 34.719 25.8339 31.7816C25.8339 31.4688 25.861 31.1696 25.9016 30.884L25.7662 0.380859L12.9237 1.4416V31.7816C12.9237 36.4597 14.2648 40.3627 16.5814 43.3546L39.2047 40.9611C37.85 38.3772 37.0913 35.2902 37.0913 31.7816Z" fill="#35E2CF"/>
|
||||
<path d="M22.542 48.1416C25.2243 49.4199 28.3672 50.0863 31.8216 50.0863C36.1295 50.0863 40.2478 48.7263 43.4855 46.1289C43.4042 46.0745 43.3365 46.0065 43.2687 45.9385L22.542 48.1416Z" fill="#35E2CF"/>
|
||||
<path d="M43.4855 46.1291C46.7367 48.6858 51.0446 50.0865 55.9893 50.0865C61.7602 50.0865 67.2061 47.6522 70.6063 43.0557L43.77 45.8979C43.6887 45.9795 43.5803 46.0475 43.4855 46.1291Z" fill="#5AADCC"/>
|
||||
<path d="M43.2687 45.9519C43.3365 46.0063 43.4178 46.0743 43.4855 46.1423C43.5803 46.0607 43.6887 45.9791 43.7835 45.9111L43.2687 45.9519Z" fill="#5AADCC"/>
|
||||
<path d="M57.791 13.4633C56.8698 13.4633 56.0705 13.5177 55.3525 13.6265L55.4067 26.301C58.3464 26.4234 60.3107 28.8985 60.3107 31.7679C60.3107 34.7054 58.2516 37.2484 55.19 37.2484C52.0607 37.2484 50.0015 34.7054 50.0015 31.7679C50.0015 31.4551 50.0286 31.1559 50.0693 30.8568L50.0015 15.6664V0.367188H49.9338L37.0913 1.42793V13.8713V31.7815C37.0913 35.3037 37.8364 38.3772 39.1911 40.9746L48.2269 40.0227L73.3699 37.3708C73.8711 35.5757 74.1556 33.6038 74.1556 31.4551C74.1692 22.4932 67.3144 13.4633 57.791 13.4633Z" fill="#5AADCC"/>
|
||||
<path d="M81.2813 26.0283V42.2115C81.2813 46.5904 83.0288 49.0655 87.1877 49.0655C91.7395 49.0655 94.6385 47.42 94.6385 37.6013V26.6131L97.4427 26.0283V50.9966L94.6385 51.391V47.352H94.5437C93.5818 49.5415 90.6692 51.5814 86.9439 51.5814C80.7936 51.5814 78.4771 48.0863 78.4771 42.5514V26.6131L81.2813 26.0283Z" fill="#5AADCC"/>
|
||||
<path d="M123.06 16.4139L125.864 15.8291V51.0104L123.06 51.5952V46.9306H122.965C121.123 49.3649 117.397 51.5952 113.428 51.5952C106.357 51.5952 100.748 46.4003 100.748 38.7167C100.748 31.5771 106.316 26.0422 113.333 26.0422C117.302 26.0422 120.594 28.1364 122.965 30.8563H123.06V16.4139ZM113.184 28.8572C107.427 28.8572 103.552 33.8617 103.552 38.7167C103.552 44.4012 107.427 48.7801 113.279 48.7801C118.698 48.7801 123.06 44.17 123.06 38.8663C123.06 32.5426 118.508 28.8572 113.184 28.8572Z" fill="#5AADCC"/>
|
||||
<path d="M151.712 16.4139L154.516 15.8291V51.0104L151.712 51.5952V46.9306H151.617C149.774 49.3649 146.049 51.5952 142.08 51.5952C135.008 51.5952 129.4 46.4003 129.4 38.7167C129.4 31.5771 134.968 26.0422 141.985 26.0422C145.954 26.0422 149.246 28.1364 151.617 30.8563H151.712V16.4139ZM141.836 28.8572C136.078 28.8572 132.204 33.8617 132.204 38.7167C132.204 44.4012 136.078 48.7801 141.931 48.7801C147.349 48.7801 151.712 44.17 151.712 38.8663C151.712 32.5426 147.16 28.8572 141.836 28.8572Z" fill="#5AADCC"/>
|
||||
<path d="M155.288 26.6131L158.051 26.0283L167.778 43.8162L176.299 26.0283L179.103 26.6131L162.888 59.9449L160.178 59.3601L166.18 46.7808L155.288 26.6131Z" fill="#5AADCC"/>
|
||||
</svg>
|
After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 55 KiB |
After Width: | Height: | Size: 75 KiB |
After Width: | Height: | Size: 48 KiB |
After Width: | Height: | Size: 51 KiB |
After Width: | Height: | Size: 58 KiB |
After Width: | Height: | Size: 60 KiB |
|
@ -0,0 +1,14 @@
|
|||
import { AxiosResponse } from 'axios';
|
||||
import { apiClient } from '../lib/apiClient';
|
||||
|
||||
export const getAuth = (login: string, password: string, locale: string ): Promise<AxiosResponse<{ jwtToken: string }>> => (
|
||||
apiClient.post(
|
||||
'/auth/login',
|
||||
{ login, password },
|
||||
{
|
||||
headers: {
|
||||
'X-User-Language': locale
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
|
@ -0,0 +1,32 @@
|
|||
import { apiClient } from '../lib/apiClient';
|
||||
import { Filter, ExpertsData, ExpertDetails } from '../types/experts';
|
||||
|
||||
export const getExpertsList = async (filter: Filter, locale: string) => {
|
||||
const response = await apiClient.post(
|
||||
'/home/coachsearch',
|
||||
{ ...filter },
|
||||
{
|
||||
headers: {
|
||||
'X-User-Language': locale,
|
||||
Authorization: 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImN0eSI6IkpXVCJ9.eyJuYW1laWQiOiIxNzIiLCJuYmYiOjE3MDM2ODMyMDgsImV4cCI6MTczNTIxOTIwOCwiaWF0IjoxNzAzNjgzMjA4fQ.KgnYfKO7oVFLlDuKhfyNN6RAaXKdeSzJd7F4r6_15AA'
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return response.data?.coaches as ExpertsData || null;
|
||||
};
|
||||
|
||||
export const getExpertById = async (id: string, locale: string) => {
|
||||
const response = await apiClient.post(
|
||||
'/home/coachdetails',
|
||||
{ id },
|
||||
{
|
||||
headers: {
|
||||
'X-User-Language': locale,
|
||||
Authorization: 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImN0eSI6IkpXVCJ9.eyJuYW1laWQiOiIxNzIiLCJuYmYiOjE3MDM2ODMyMDgsImV4cCI6MTczNTIxOTIwOCwiaWF0IjoxNzAzNjgzMjA4fQ.KgnYfKO7oVFLlDuKhfyNN6RAaXKdeSzJd7F4r6_15AA'
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return response.data as ExpertDetails || null;
|
||||
};
|
|
@ -9,7 +9,7 @@ export default function Directions() {
|
|||
<div className="main-popular__coll">
|
||||
<div className="b-popular">
|
||||
<div className="b-popular__image">
|
||||
<img className="" src="/images/popular.png" alt=""/>
|
||||
<img className="" src="/images/popular1.png" alt=""/>
|
||||
</div>
|
||||
<div className="b-popular__inner">
|
||||
<div className="b-popular__title">Work Life Balance</div>
|
||||
|
@ -23,10 +23,10 @@ export default function Directions() {
|
|||
<div className="main-popular__coll">
|
||||
<div className="b-popular">
|
||||
<div className="b-popular__image">
|
||||
<img className="" src="/images/popular.png" alt=""/>
|
||||
<img className="" src="/images/popular2.png" alt=""/>
|
||||
</div>
|
||||
<div className="b-popular__inner">
|
||||
<div className="b-popular__title">Work Life Balance</div>
|
||||
<div className="b-popular__title">Strategic Session</div>
|
||||
<div className="b-popular__wrap-link">
|
||||
<a className="b-popular__link" href="">23 experts</a> |
|
||||
<a className="b-popular__link" href="">245 offers</a>
|
||||
|
@ -37,10 +37,10 @@ export default function Directions() {
|
|||
<div className="main-popular__coll d-none d-md-block">
|
||||
<div className="b-popular">
|
||||
<div className="b-popular__image">
|
||||
<img className="" src="/images/popular.png" alt=""/>
|
||||
<img className="" src="/images/popular3.png" alt=""/>
|
||||
</div>
|
||||
<div className="b-popular__inner">
|
||||
<div className="b-popular__title">Work Life Balance</div>
|
||||
<div className="b-popular__title">Personal Growth</div>
|
||||
<div className="b-popular__wrap-link">
|
||||
<a className="b-popular__link" href="">23 experts</a> |
|
||||
<a className="b-popular__link" href="">245 offers</a>
|
||||
|
@ -51,10 +51,10 @@ export default function Directions() {
|
|||
<div className="main-popular__coll d-none d-lg-block">
|
||||
<div className="b-popular">
|
||||
<div className="b-popular__image">
|
||||
<img className="" src="/images/popular.png" alt=""/>
|
||||
<img className="" src="/images/popular4.png" alt=""/>
|
||||
</div>
|
||||
<div className="b-popular__inner">
|
||||
<div className="b-popular__title">Work Life Balance</div>
|
||||
<div className="b-popular__title">Career Planning</div>
|
||||
<div className="b-popular__wrap-link">
|
||||
<a className="b-popular__link" href="">23 experts</a> |
|
||||
<a className="b-popular__link" href="">245 offers</a>
|
||||
|
@ -65,10 +65,10 @@ export default function Directions() {
|
|||
<div className="main-popular__coll d-none d-lg-block">
|
||||
<div className="b-popular">
|
||||
<div className="b-popular__image">
|
||||
<img className="" src="/images/popular.png" alt=""/>
|
||||
<img className="" src="/images/popular5.png" alt=""/>
|
||||
</div>
|
||||
<div className="b-popular__inner">
|
||||
<div className="b-popular__title">Work Life Balance</div>
|
||||
<div className="b-popular__title">Executive Coaching</div>
|
||||
<div className="b-popular__wrap-link">
|
||||
<a className="b-popular__link" href="">23 experts</a> |
|
||||
<a className="b-popular__link" href="">245 offers</a>
|
||||
|
@ -79,10 +79,10 @@ export default function Directions() {
|
|||
<div className="main-popular__coll d-none d-xl-block">
|
||||
<div className="b-popular">
|
||||
<div className="b-popular__image">
|
||||
<img className="" src="/images/popular.png" alt=""/>
|
||||
<img className="" src="/images/popular6.png" alt=""/>
|
||||
</div>
|
||||
<div className="b-popular__inner">
|
||||
<div className="b-popular__title">Work Life Balance</div>
|
||||
<div className="b-popular__title">Career Development</div>
|
||||
<div className="b-popular__wrap-link">
|
||||
<a className="b-popular__link" href="">23 experts</a> |
|
||||
<a className="b-popular__link" href="">245 offers</a>
|
||||
|
|
|
@ -1,76 +1,20 @@
|
|||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
import { Avatar, List, Typography, Tag } from 'antd';
|
||||
import { RightOutlined } from '@ant-design/icons';
|
||||
import { Link } from '../../../../navigation';
|
||||
import { ExpertsFilter, ExpertsAdditionalFilter } from '../../../../components/Experts';
|
||||
import { CustomPagination } from '../../../../components/view';
|
||||
import { ExpertsFilter } from '../../../../components/Experts/Filter';
|
||||
import { ExpertsAdditionalFilter } from '../../../../components/Experts/AdditionalFilter';
|
||||
import { ExpertsList } from '../../../../components/Experts/ExpertsList';
|
||||
import { getExpertsList } from '../../../../actions/experts';
|
||||
|
||||
const { Text } = Typography;
|
||||
|
||||
const data = Array.from({ length: 10 }).map((_, i) => ({
|
||||
href: '/',
|
||||
name: 'Matthew Weeks',
|
||||
avatar: '/images/person.png',
|
||||
duration: '45min',
|
||||
price: '45$',
|
||||
skills: ['Engineering & Data', 'Soft skills', 'Interview'],
|
||||
speciality: 'Senior Software Engineer',
|
||||
specialityDesc: 'Auth0',
|
||||
description: 'I have worked across a variety of organizations, lead teams, and delivered quality software for 8 years. In that time I\'ve worked as an independent consultant, at agencies as a team lead, and as a senior engineer at Auth0. I also host a podcast https://anchor.fm/work-in-programming where I break down how …'
|
||||
}));
|
||||
|
||||
export default function Experts() {
|
||||
const expertsList = (
|
||||
<List
|
||||
itemLayout="vertical"
|
||||
size="large"
|
||||
pagination={{
|
||||
className: 'pagination',
|
||||
onChange: (page) => {
|
||||
console.log(page);
|
||||
},
|
||||
pageSize: 5
|
||||
}}
|
||||
dataSource={data}
|
||||
renderItem={(item) => (
|
||||
<List.Item key={item.name}>
|
||||
<List.Item.Meta
|
||||
avatar={<Avatar src={item.avatar} />}
|
||||
title={item.name}
|
||||
description={(
|
||||
<div className="card-profile__header__price">
|
||||
{item.price} <span>/ {item.duration}</span>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<div className="card-profile__skills">
|
||||
<div className="skills__list">
|
||||
{item.skills.map((skill) => <Tag color="#f50">{skill}</Tag>)}
|
||||
<div className="skills__list__item">Engineering & Data</div>
|
||||
<div className="skills__list__more">+6</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card-profile__title">{item.speciality}</div>
|
||||
<div className="card-profile__subtitle">{item.specialityDesc}</div>
|
||||
<div className="card-profile__desc">{item.description}</div>
|
||||
<div className="card-profile__footer">
|
||||
<Link href={item.href as any}>
|
||||
<Text
|
||||
copyable={{
|
||||
icon: <RightOutlined key="copy-icon" style={{ fontSize: '15px' }}/>,
|
||||
onCopy: undefined,
|
||||
tooltips: false
|
||||
}}
|
||||
>
|
||||
Details
|
||||
</Text>
|
||||
</Link>
|
||||
</div>
|
||||
</List.Item>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
export default async function Experts({ params }: { params: { locale: string } }) {
|
||||
const data = await getExpertsList({
|
||||
"themesTagIds": [
|
||||
1,2,3,4,5,6,7,8
|
||||
],
|
||||
"priceFrom": null,
|
||||
"priceTo": null,
|
||||
"durationFrom": null,
|
||||
"durationTo": null
|
||||
}, params.locale);
|
||||
|
||||
return (
|
||||
<div className="main-find">
|
||||
|
@ -83,54 +27,12 @@ export default function Experts() {
|
|||
</div>
|
||||
<div className="row">
|
||||
<div className="col-xl-3 col-lg-4 d-none d-lg-block">
|
||||
<ExpertsFilter />
|
||||
<ExpertsFilter locale={params.locale} />
|
||||
</div>
|
||||
<div className="col-xl-9 col-lg-8 ">
|
||||
<ExpertsAdditionalFilter />
|
||||
<div className="search-result">
|
||||
<div className="card-profile">
|
||||
<div className="card-profile__header">
|
||||
<div className="card-profile__header__portrait">
|
||||
<img src="/images/person.png" className="" alt="" />
|
||||
</div>
|
||||
<div className="card-profile__header__inner">
|
||||
<div className="card-profile__header__name">Matthew Weeks</div>
|
||||
<div className="card-profile__header__price">
|
||||
45$ <span>/ 45min</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card-profile__skills">
|
||||
<div className="skills__list">
|
||||
<div className="skills__list__item">Engineering & Data</div>
|
||||
<div className="skills__list__item">Engineering & Data</div>
|
||||
<div className="skills__list__more">+6</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card-profile__title">Senior Software Engineer</div>
|
||||
<div className="card-profile__subtitle">Auth0</div>
|
||||
<div className="card-profile__desc">
|
||||
I have worked across a variety of organizations, lead teams, and delivered quality
|
||||
software for 8 years. In that time I've worked as an independent consultant, at
|
||||
agencies as a team lead, and as a senior engineer at Auth0. I also host a podcast
|
||||
https://anchor.fm/work-in-programming where I break down how …
|
||||
</div>
|
||||
<div className="card-profile__footer">
|
||||
<a href="#">Details
|
||||
<img className="" src="/images/chevron-forward.svg" alt="" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{expertsList}
|
||||
</div>
|
||||
<ul className="pagination">
|
||||
<li className="page-item"><a className="page-link" href="#">1</a></li>
|
||||
<li className="page-item active" aria-current="page">
|
||||
<a className="page-link" href="#">2</a>
|
||||
</li>
|
||||
<li className="page-item"><a className="page-link" href="#">3</a></li>
|
||||
<li className="page-item"><a className="page-link" href="#">4</a></li>
|
||||
</ul>
|
||||
<ExpertsList data={data} locale={params.locale} />
|
||||
<CustomPagination total={20} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
import React, { ReactNode } from 'react';
|
||||
import { getTranslations } from 'next-intl/server';
|
||||
|
||||
export async function generateMetadata({
|
||||
params: { locale }
|
||||
}: { params: { locale: string }}) {
|
||||
const t = await getTranslations({ locale, namespace: 'Main' });
|
||||
|
||||
return {
|
||||
title: t('title'),
|
||||
description: t('description'),
|
||||
};
|
||||
}
|
||||
// import { getTranslations } from 'next-intl/server';
|
||||
//
|
||||
// export async function generateMetadata({
|
||||
// params: { locale }
|
||||
// }: { params: { locale: string }}) {
|
||||
// const t = await getTranslations({ locale, namespace: 'Main' });
|
||||
//
|
||||
// return {
|
||||
// title: t('title'),
|
||||
// description: t('description'),
|
||||
// };
|
||||
// }
|
||||
|
||||
export default function MainLayout({ children, news, directions, experts }: {
|
||||
children: ReactNode,
|
||||
|
|
|
@ -19,12 +19,20 @@ export default function Home() {
|
|||
<p className="main-top__text">from a mentor, and getting your feet wet with coaching.</p>
|
||||
</div>
|
||||
<div className="main-top__wrap-btn">
|
||||
<a href="#" className="main-top__btn main-top__btn--apple">
|
||||
<a
|
||||
href="https://apps.apple.com/us/app/bbuddy/id6443601377?platform=iphone"
|
||||
className="main-top__btn main-top__btn--apple"
|
||||
target="_blank"
|
||||
>
|
||||
<img className="" src="/images/logo-apple.svg" alt=""/>
|
||||
<span className="line" />
|
||||
AppStore
|
||||
</a>
|
||||
<a href="#" className="main-top__btn main-top__btn--android">
|
||||
<a
|
||||
href="https://play.google.com/store/apps/details?id=com.bbuddy.whistle"
|
||||
className="main-top__btn main-top__btn--android"
|
||||
target="_blank"
|
||||
>
|
||||
<img className="" src="/images/logo-android.svg" alt=""/>
|
||||
<span className="line" />
|
||||
GooglePlay
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import React from 'react';
|
||||
import type { Metadata } from 'next';
|
||||
import { useTranslations } from 'next-intl';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Bbuddy - Account - Information',
|
||||
|
@ -7,9 +8,68 @@ export const metadata: Metadata = {
|
|||
};
|
||||
|
||||
export default function Information() {
|
||||
const t = useTranslations('Account.LegalInformation');
|
||||
|
||||
return (
|
||||
<div>
|
||||
Страница Информации о пользователе
|
||||
</div>
|
||||
<>
|
||||
<ol className="breadcrumb">
|
||||
<li className="breadcrumb-item active" aria-current="page">{t('title')}</li>
|
||||
</ol>
|
||||
<div className="base-text">
|
||||
Welcome to the B BUDDY LTD’s privacy policy. <br />
|
||||
B BUDDY LTD respects your privacy and is committed to protecting your personal data. This privacy policy
|
||||
will inform you as to how we collect, use and look after your personal data. It further describes your
|
||||
privacy rights and the control you can exercise in relation to your personal data.
|
||||
</div>
|
||||
<h3 className="title-h3">
|
||||
Important Information
|
||||
</h3>
|
||||
<div className="base-text">
|
||||
This privacy policy is issued on behalf of B BUDDY LTD which is the controller of your personal data. B
|
||||
BUDDY LTD is a limited liability company registered in the Republic of Cyprus with registration number
|
||||
HE 417576.
|
||||
<br />
|
||||
This privacy policy is addressed to individuals outside B BUDDY LTD with whom we interact, including
|
||||
individual clients, representatives, directors, shareholders, beneficial owners, coaches and/or
|
||||
mentors and/or consultants of our application and/or website as well as other users of our services
|
||||
and suppliers.
|
||||
</div>
|
||||
<h3 className="title-h3">What Personal Date We Collect About You?</h3>
|
||||
<div className="base-text">
|
||||
We may collect, use, store and transfer different kinds of personal data about you which we have grouped
|
||||
together as follows:<br />
|
||||
Identity Data includes first name, maiden name, last name, username or similar identifier, title,
|
||||
date of birth, gender;<br />
|
||||
Contact Data includes billing address, delivery address, email address, and telephone numbers
|
||||
(including mobile telephone number(s)), postal address.<br />
|
||||
Business Data includes date identifying you in relation to matters on which you instruct us or
|
||||
in which you are involved such as diplomas and any other educational document or
|
||||
certificate;<br />
|
||||
Consent Records Data includes records of any consents you have given us, together with the date,
|
||||
means of consent and any other information provided such as the subject matter of the consent
|
||||
provided;<br />
|
||||
Supplier Data includes contact details and other information about you or your company or
|
||||
organisation where you provide services to B BUDDY LTD;<br />
|
||||
Tracker (i.e. any technology - e.g Cookies, unique identifiers, web beacons, embedded scripts,
|
||||
e-tags and fingerprinting - that enables the tracking of Users, for example by accessing or
|
||||
storing information on the User’s device);<br />
|
||||
Usage Data (i.e information collected automatically through this Website (or third-party
|
||||
services employed in this Website), which can include: the IP addresses or domain names of the
|
||||
computers utilized by the Users who use this Website, the URI addresses (Uniform Resource
|
||||
Identifier), the time of the request, the method utilized to submit the request to the server,
|
||||
the size of the file received in response, the numerical code indicating the status of the
|
||||
server's answer (successful outcome, error, etc.), the country of origin, the features of the
|
||||
browser and the operating system utilized by the User, the various time details per visit (e.g.,
|
||||
the time spent on each page within the Application) and the details about the path followed
|
||||
within the Application with special reference to the sequence of pages visited, and other
|
||||
parameters about the device operating system and/or the User's IT environment.);<br />
|
||||
Any other information relating to you which you may provide us with, such as health personal
|
||||
data, if required by us to be able to provide our services to you.<br />
|
||||
B BUDDY LTD does not collect any payment details data as they are collected directly by Stripe,
|
||||
Inc. which is responsible to effect the payments. Stripe, Inc. is a PCI Service Provider Level 1
|
||||
and it is obliged to follow PCI compliance and the General Data Protection Regulations 2018
|
||||
(GDPR).
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,15 +1,55 @@
|
|||
import React from 'react';
|
||||
import type { Metadata } from 'next';
|
||||
import { useTranslations } from 'next-intl';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Bbuddy - Account - Information',
|
||||
description: 'Bbuddy desc information'
|
||||
title: 'Bbuddy - Account - Notifications',
|
||||
description: 'Bbuddy desc notifications'
|
||||
};
|
||||
|
||||
export default function Information() {
|
||||
export default function Notifications() {
|
||||
const t = useTranslations('Account.Notifications');
|
||||
|
||||
return (
|
||||
<div>
|
||||
Страница Информации о пользователе
|
||||
</div>
|
||||
<>
|
||||
<ol className="breadcrumb">
|
||||
<li className="breadcrumb-item active" aria-current="page">{t('title')}</li>
|
||||
</ol>
|
||||
<div className="list-notifications ">
|
||||
<div className="b-notifications primary">
|
||||
<div className="b-notifications__title">Notification Headline</div>
|
||||
<div className="b-notifications__text">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc auctor leo eu justo molestie
|
||||
</div>
|
||||
<div className="b-notifications__date">25 may 2022</div>
|
||||
<div className="b-notifications__inner">
|
||||
<a href="#" className="b-notifications__read">{t('read')}</a>
|
||||
<a href="#" className="b-notifications__delete">{t('delete')}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div className="b-notifications primary">
|
||||
<div className="b-notifications__title">Notification Headline</div>
|
||||
<div className="b-notifications__text">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc auctor leo eu justo molestie
|
||||
</div>
|
||||
<div className="b-notifications__date">25 may 2022</div>
|
||||
<div className="b-notifications__inner">
|
||||
<a href="#" className="b-notifications__read">{t('read')}</a>
|
||||
<a href="#" className="b-notifications__delete">{t('delete')}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div className="b-notifications danger">
|
||||
<div className="b-notifications__title">Notification Headline</div>
|
||||
<div className="b-notifications__text">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc auctor leo eu justo molestie
|
||||
</div>
|
||||
<div className="b-notifications__date">25 may 2022</div>
|
||||
<div className="b-notifications__inner">
|
||||
<a href="#" className="b-notifications__read">{t('read')}</a>
|
||||
<a href="#" className="b-notifications__delete">{t('delete')}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,15 +1,25 @@
|
|||
import React from 'react';
|
||||
import type { Metadata } from 'next';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { SessionsTabs } from '../../../../components/Account';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Bbuddy - Account - Information',
|
||||
description: 'Bbuddy desc information'
|
||||
title: 'Bbuddy - Account - Sessions',
|
||||
description: 'Bbuddy desc sessions'
|
||||
};
|
||||
|
||||
export default function Sessions() {
|
||||
const t = useTranslations('Account.Sessions');
|
||||
|
||||
return (
|
||||
<div>
|
||||
Страница Информации о пользователе
|
||||
</div>
|
||||
<SessionsTabs
|
||||
intlConfig={{
|
||||
upcoming: t('upcoming-sessions'),
|
||||
requested: t('sessions-requested'),
|
||||
recent: t('recent-sessions'),
|
||||
selectTopicLabel: t('topic'),
|
||||
dateLabel: t('day-start')
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
import React from 'react';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { Link } from '../../../../../navigation';
|
||||
|
||||
export default function ChangePassword({ params }: { params: { userId: string } }) {
|
||||
const t = useTranslations('Account.Settings');
|
||||
|
||||
return (
|
||||
<>
|
||||
<ol className="breadcrumb">
|
||||
<li className="breadcrumb-item">
|
||||
<Link href={`/${params.userId}/settings` as any}>
|
||||
{t('title')}
|
||||
</Link>
|
||||
</li>
|
||||
<li className="breadcrumb-item active" aria-current="page">{t('change-password')}</li>
|
||||
</ol>
|
||||
<form className="form-settings" action="">
|
||||
<div className="form-field password-hide">
|
||||
<input type="text" placeholder={t('old-password')} className="base-input" id="" value="" />
|
||||
</div>
|
||||
<div className="form-field password-hide">
|
||||
<input type="text" placeholder={t('new-password')} className="base-input" id="" value="" />
|
||||
</div>
|
||||
<div className="form-field password-show">
|
||||
<input className="base-input" type="text" placeholder={t('confirm-password')} id="" value="" />
|
||||
</div>
|
||||
<button className="btn-apply">{t('save')}</button>
|
||||
</form>
|
||||
</>
|
||||
);
|
||||
};
|
|
@ -1,15 +1,48 @@
|
|||
import React from 'react';
|
||||
import type { Metadata } from 'next';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import {Link} from "../../../../navigation";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Bbuddy - Account - Information',
|
||||
description: 'Bbuddy desc information'
|
||||
title: 'Bbuddy - Account - Profile Settings',
|
||||
description: 'Bbuddy desc Profile settings'
|
||||
};
|
||||
|
||||
export default function Information() {
|
||||
export default function Settings({ params }: { params: { userId: string } }) {
|
||||
const t = useTranslations('Account.Settings');
|
||||
|
||||
return (
|
||||
<div>
|
||||
Страница Информации о пользователе
|
||||
</div>
|
||||
<>
|
||||
<ol className="breadcrumb">
|
||||
<li className="breadcrumb-item active" aria-current="page">{t('title')}</li>
|
||||
</ol>
|
||||
<form className="form-settings" action="">
|
||||
<div className="user-avatar">
|
||||
<div className="user-avatar__edit">
|
||||
<input className="" type="file" id="input-file" />
|
||||
<label htmlFor="input-file" className="form-label" />
|
||||
</div>
|
||||
<div className="user-avatar__text">{t('photo-desc')}</div>
|
||||
</div>
|
||||
<div className="form-field">
|
||||
<input type="text" placeholder={t('name')} className="base-input" id="" value="" />
|
||||
</div>
|
||||
<div className="form-field">
|
||||
<input type="text" placeholder={t('surname')} className="base-input" id="" value="" />
|
||||
</div>
|
||||
<div className="form-field date">
|
||||
<input className="base-input " type="text" placeholder={t('birthday')} id="" value="" />
|
||||
</div>
|
||||
<div className="form-field">
|
||||
<input type="email" placeholder={t('email')} className="base-input" id="" value="" />
|
||||
</div>
|
||||
<div className="form-link">
|
||||
<Link href={`/${params.userId}/settings/change-password` as any}>
|
||||
{t('change-password')}
|
||||
</Link>
|
||||
</div>
|
||||
<button className="btn-apply">{t('save')}</button>
|
||||
</form>
|
||||
</>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,15 +1,23 @@
|
|||
import React from 'react';
|
||||
import type { Metadata } from 'next';
|
||||
import {useTranslations} from "next-intl";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Bbuddy - Account - Information',
|
||||
description: 'Bbuddy desc information'
|
||||
title: 'Bbuddy - Account - Help & Support',
|
||||
description: 'Bbuddy desc help & support'
|
||||
};
|
||||
|
||||
export default function Information() {
|
||||
export default function Support() {
|
||||
const t = useTranslations('Account.Support');
|
||||
|
||||
return (
|
||||
<div>
|
||||
Страница Информации о пользователе
|
||||
</div>
|
||||
<>
|
||||
<ol className="breadcrumb">
|
||||
<li className="breadcrumb-item active" aria-current="page">{t('title')}</li>
|
||||
</ol>
|
||||
<div className="base-text">
|
||||
some text
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@ export default function WorkWithUs() {
|
|||
<ol className="breadcrumb">
|
||||
<li className="breadcrumb-item active" aria-current="page">{t('title')}</li>
|
||||
</ol>
|
||||
|
||||
<div className="b-info">
|
||||
<div className="image-info">
|
||||
<img className="" src="/images/info.png" alt="" />
|
||||
|
|
|
@ -2,18 +2,79 @@ import React from 'react';
|
|||
import type { Metadata } from 'next';
|
||||
import { notFound } from 'next/navigation';
|
||||
import { Link } from '../../../../navigation';
|
||||
import { getExpertById, getExpertsList } from '../../../../actions/experts';
|
||||
import {
|
||||
ExpertCard,
|
||||
ExpertCertificate,
|
||||
ExpertInformation,
|
||||
ExpertPractice
|
||||
} from '../../../../components/Experts/ExpertDetails';
|
||||
import { Details } from '../../../../types/experts';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Bbuddy - Experts item',
|
||||
description: 'Bbuddy desc experts'
|
||||
};
|
||||
|
||||
export function generateStaticParams() {
|
||||
return [{ expertId: '1' }, { expertId: '2' }];
|
||||
export async function generateStaticParams({
|
||||
params: { locale },
|
||||
}: { params: { locale: string } }) {
|
||||
const result: { locale: string, expertId: string }[] = [];
|
||||
const experts = await getExpertsList({
|
||||
"themesTagIds": [
|
||||
1,2,3,4,5,6,7,8
|
||||
],
|
||||
"priceFrom": null,
|
||||
"priceTo": null,
|
||||
"durationFrom": null,
|
||||
"durationTo": null
|
||||
}, locale);
|
||||
|
||||
experts?.forEach(({ id }) => {
|
||||
result.push({ locale, expertId: id.toString() });
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export default function ExpertItem({ params }: { params: { expertId: string } }) {
|
||||
if (!params?.expertId) notFound();
|
||||
export default async function ExpertItem({ params: { expertId = '', locale} }: { params: { expertId: string, locale: string } }) {
|
||||
if (!expertId) notFound();
|
||||
|
||||
const expert = await getExpertById(expertId, locale);
|
||||
|
||||
const getAssociationLevel = (accLevelId?: number) => {
|
||||
if (accLevelId) {
|
||||
const [cur] = (expert?.associationLevels || []).filter(({ id }) => id === accLevelId) || [];
|
||||
|
||||
return cur?.name || '';
|
||||
}
|
||||
|
||||
return '';
|
||||
};
|
||||
|
||||
const getAssociation = (accLevelId?: number) => {
|
||||
if (accLevelId) {
|
||||
const [curLevel] = (expert?.associationLevels || []).filter(({ id }) => id === accLevelId) || [];
|
||||
if (curLevel) {
|
||||
const [cur] = (expert?.associations || []).filter(({ id }) => id === curLevel.associationId) || [];
|
||||
return cur?.name || '';
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
};
|
||||
|
||||
const generateDescription = ({ id, title, description, document }: Details) => (
|
||||
<div key={id}>
|
||||
<h3 className="title-h3">{title}</h3>
|
||||
<p className="base-text">{description}</p>
|
||||
{document && (
|
||||
<div className="sertific">
|
||||
<ExpertCertificate document={document} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="b-page">
|
||||
|
@ -24,125 +85,37 @@ export default function ExpertItem({ params }: { params: { expertId: string } })
|
|||
Back to experts list
|
||||
</Link>
|
||||
</div>
|
||||
<div className="expert-card">
|
||||
<div className="expert-card__wrap">
|
||||
<div className="expert-card__avatar">
|
||||
<img src="/images/person.png" className="" alt="" />
|
||||
</div>
|
||||
<div className="expert-card__inner">
|
||||
<h1 className="expert-card__title">{`Matthew Weeks | id ${params.expertId}`}</h1>
|
||||
<div className="expert-card__info">
|
||||
<span>12 Practice hours</span>
|
||||
<i>|</i>
|
||||
<span>15 Supervision per year</span>
|
||||
</div>
|
||||
<div className="expert-card__rating">
|
||||
<img src="/images/stars.svg" className="" alt="" />
|
||||
<span>4/5 (out of 345)</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="expert-card__wrap-btn">
|
||||
<a href="#" className="btn-apply">
|
||||
<img src="/images/calendar-outline.svg" className="" alt="" />
|
||||
Schedule
|
||||
</a>
|
||||
<a href="#" className="btn-video">
|
||||
<img src="/images/videocam-outline.svg" className="" alt="" />
|
||||
Video
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<h2 className="title-h2">Current Offer</h2>
|
||||
<div className="skills__list">
|
||||
<div className="skills__list__item">Engineering & Data</div>
|
||||
<div className="skills__list__item">Communication</div>
|
||||
<div className="skills__list__item">Communication</div>
|
||||
</div>
|
||||
<p className="base-text">
|
||||
Hello, my name is Marcelo. I am a Senior UX Designer with more than 6 years of experience working
|
||||
with the largest companies in the world such as Disney, Globant and currently IBM.
|
||||
During my career, I have helped organizations solve complex problems using aesthetically pleasing
|
||||
designs with design while building teams and mentoring other designers.
|
||||
I can help you: <br />
|
||||
Prepare for interviews, prepare your resume or CV and work on your LinkedIn profile <br />
|
||||
Get ready for whiteboard challenges and take-home exercises <br />
|
||||
Create a great portfolio and case study presentation. <br />
|
||||
Provide industry information. <br />
|
||||
Professional orientation <br />
|
||||
Strategic thinking <br /><br />
|
||||
<ExpertCard expert={expert} />
|
||||
<ExpertInformation expert={expert} locale={locale} />
|
||||
|
||||
Oh, and I also speak Spanish!
|
||||
</p>
|
||||
<div className="wrap-btn-prise">
|
||||
<a href="#" className="btn-apply">
|
||||
Sign Up Now
|
||||
</a>
|
||||
<div className="wrap-btn-prise__text">
|
||||
45$ <span> / 45min</span>
|
||||
</div>
|
||||
</div>
|
||||
<h2 className="title-h2">Expert Background</h2>
|
||||
<p className="base-text">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam aliquet, lectus nec viverra
|
||||
malesuada, ligula sem tempor risus, non posuere urna diam a libero.
|
||||
</p>
|
||||
<h3 className="title-h3">Education</h3>
|
||||
<p className="base-text">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam aliquet, lectus nec viverra
|
||||
malesuada, ligula sem tempor risus, non posuere urna diam a libero.
|
||||
</p>
|
||||
<div className="sertific">
|
||||
<img src="/images/sertific.png" className="" alt="" />
|
||||
</div>
|
||||
<h3 className="title-h3">Professional Certification</h3>
|
||||
<p className="base-text">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam aliquet, lectus nec viverra
|
||||
malesuada, ligula sem tempor risus, non posuere urna diam a libero.
|
||||
</p>
|
||||
<h3 className="title-h3">Trainings | Seminars | Courses</h3>
|
||||
<p className="base-text">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam aliquet, lectus nec viverra
|
||||
malesuada, ligula sem tempor risus, non posuere urna diam a libero.
|
||||
</p>
|
||||
<h3 className="title-h3">MBA Information</h3>
|
||||
<p className="base-text">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam aliquet, lectus nec viverra
|
||||
malesuada, ligula sem tempor risus, non posuere urna diam a libero.
|
||||
</p>
|
||||
<h3 className="title-h3">Managerial Experience</h3>
|
||||
<p className="base-text">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam aliquet, lectus nec viverra
|
||||
malesuada, ligula sem tempor risus, non posuere urna diam a libero.
|
||||
</p>
|
||||
<h3 className="title-h3">Entrepreneurial Experience</h3>
|
||||
<p className="base-text">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam aliquet, lectus nec viverra
|
||||
malesuada, ligula sem tempor risus, non posuere urna diam a libero.
|
||||
</p>
|
||||
<h3 className="title-h3">Successful Cases From Practice</h3>
|
||||
<div className="case-list">
|
||||
<div className="skills__list">
|
||||
<div className="skills__list__item">Engineering & Data</div>
|
||||
<div className="skills__list__item">Communication</div>
|
||||
<div className="skills__list__item">Communication</div>
|
||||
{expert?.publicCoachDetails?.educations && expert.publicCoachDetails.educations?.map(generateDescription)}
|
||||
{expert?.publicCoachDetails?.certificates && expert.publicCoachDetails.certificates.length > 0 && (
|
||||
<div>
|
||||
<h3 className="title-h3">Professional Certification</h3>
|
||||
{expert.publicCoachDetails.certificates?.map((cert) => (
|
||||
<div key={cert.id}>
|
||||
<p className="base-text">
|
||||
{`${getAssociationLevel(cert?.associationLevelId)} ${getAssociation(cert?.associationLevelId)}`}
|
||||
</p>
|
||||
{cert.document && (
|
||||
<div className="sertific">
|
||||
<ExpertCertificate document={cert.document} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<p className="base-text">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam aliquet, lectus nec viverra
|
||||
malesuada, ligula sem tempor risus, non posuere urna diam a libero.
|
||||
</p>
|
||||
</div>
|
||||
<div className="case-list">
|
||||
<div className="skills__list">
|
||||
<div className="skills__list__item">Engineering & Data</div>
|
||||
<div className="skills__list__item">Communication</div>
|
||||
<div className="skills__list__item">Communication</div>
|
||||
</div>
|
||||
<p className="base-text">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam aliquet, lectus nec viverra
|
||||
malesuada, ligula sem tempor risus, non posuere urna diam a libero.
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
{expert?.publicCoachDetails?.trainings && expert.publicCoachDetails.trainings?.map(generateDescription)}
|
||||
{expert?.publicCoachDetails?.mbas && expert.publicCoachDetails.mbas?.map(generateDescription)}
|
||||
{expert?.publicCoachDetails?.experiences && expert.publicCoachDetails.experiences?.map(generateDescription)}
|
||||
<ExpertPractice expert={expert} />
|
||||
|
||||
<h2 className="title-h2">All Offers by this Expert</h2>
|
||||
<div className="offers-list">
|
||||
<div className="card-profile">
|
||||
|
|
|
@ -1,14 +1,27 @@
|
|||
import React from 'react';
|
||||
import type { Metadata } from 'next';
|
||||
import { ExpertsFilter, ExpertsAdditionalFilter } from '../../../components/Experts';
|
||||
import { getExpertsList } from '../../../actions/experts';
|
||||
import { ExpertsFilter } from '../../../components/Experts/Filter';
|
||||
import { ExpertsAdditionalFilter } from '../../../components/Experts/AdditionalFilter';
|
||||
import { ExpertsList } from '../../../components/Experts/ExpertsList';
|
||||
import { CustomPagination } from '../../../components/view';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Bbuddy - Experts',
|
||||
description: 'Bbuddy desc experts'
|
||||
};
|
||||
|
||||
export default function Experts({ searchParams }: { searchParams: { [key: string]: string | string[] | undefined } }) {
|
||||
export default async function Experts({ params, searchParams }: { params: { locale: string }, searchParams: { [key: string]: string | string[] | undefined } }) {
|
||||
console.log('search params', searchParams);
|
||||
const data = await getExpertsList({
|
||||
"themesTagIds": [
|
||||
1,2,3,4,5,6,7,8
|
||||
],
|
||||
"priceFrom": null,
|
||||
"priceTo": null,
|
||||
"durationFrom": null,
|
||||
"durationTo": null
|
||||
}, params.locale);
|
||||
|
||||
return (
|
||||
<div className="page-search">
|
||||
|
@ -17,162 +30,17 @@ export default function Experts({ searchParams }: { searchParams: { [key: string
|
|||
<div className="main-find__top">
|
||||
<h2 className="title-h2">Find a expert</h2>
|
||||
<div className="open-filter">
|
||||
<img src="/images/options-outline.svg" className="" alt="" />
|
||||
<img src="/images/options-outline.svg" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-xl-3 col-lg-4 d-none d-lg-block">
|
||||
<ExpertsFilter />
|
||||
<ExpertsFilter locale={params.locale} />
|
||||
</div>
|
||||
<div className="col-xl-9 col-lg-8 ">
|
||||
<ExpertsAdditionalFilter />
|
||||
<div className="search-result">
|
||||
<div className="card-profile">
|
||||
<div className="card-profile__header">
|
||||
<div className="card-profile__header__portrait">
|
||||
<img src="/images/person.png" className="" alt="" />
|
||||
</div>
|
||||
<div className="card-profile__header__inner">
|
||||
<div className="card-profile__header__name">Matthew Weeks</div>
|
||||
<div className="card-profile__header__price">
|
||||
45$ <span>/ 45min</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card-profile__skills">
|
||||
<div className="skills__list">
|
||||
<div className="skills__list__item">Engineering & Data</div>
|
||||
<div className="skills__list__item">Engineering & Data</div>
|
||||
<div className="skills__list__more">+6</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card-profile__title">Senior Software Engineer</div>
|
||||
<div className="card-profile__subtitle">Auth0</div>
|
||||
<div className="card-profile__desc">
|
||||
I have worked across a variety of organizations, lead teams, and delivered
|
||||
quality software for 8 years. In that time I've worked as an independent
|
||||
consultant, at agencies as a team lead, and as a senior engineer at Auth0. I
|
||||
also host a podcast https://anchor.fm/work-in-programming where I break down how
|
||||
…
|
||||
</div>
|
||||
<div className="card-profile__footer">
|
||||
<a href="#">Details
|
||||
<img className="" src="/images/chevron-forward.svg" alt="" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card-profile">
|
||||
<div className="card-profile__header">
|
||||
<div className="card-profile__header__portrait">
|
||||
<img src="/images/person.png" className="" alt="" />
|
||||
</div>
|
||||
<div className="card-profile__header__inner">
|
||||
<div className="card-profile__header__name">Matthew Weeks</div>
|
||||
<div className="card-profile__header__price">
|
||||
45$ <span>/ 45min</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card-profile__skills">
|
||||
<div className="skills__list">
|
||||
<div className="skills__list__item">Engineering & Data</div>
|
||||
<div className="skills__list__item">Engineering & Data</div>
|
||||
<div className="skills__list__more">+6</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card-profile__title">Senior Software Engineer</div>
|
||||
<div className="card-profile__subtitle">Auth0</div>
|
||||
<div className="card-profile__desc">
|
||||
I have worked across a variety of organizations, lead teams, and delivered
|
||||
quality software for 8 years. In that time I've worked as an independent
|
||||
consultant, at agencies as a team lead, and as a senior engineer at Auth0. I
|
||||
also host a podcast https://anchor.fm/work-in-programming where I break down how
|
||||
…
|
||||
</div>
|
||||
<div className="card-profile__footer">
|
||||
<a href="#">Details
|
||||
<img className="" src="/images/chevron-forward.svg" alt="" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card-profile">
|
||||
<div className="card-profile__header">
|
||||
<div className="card-profile__header__portrait">
|
||||
<img src="/images/person.png" className="" alt="" />
|
||||
</div>
|
||||
<div className="card-profile__header__inner">
|
||||
<div className="card-profile__header__name">Matthew Weeks</div>
|
||||
<div className="card-profile__header__price">
|
||||
45$ <span>/ 45min</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card-profile__skills">
|
||||
<div className="skills__list">
|
||||
<div className="skills__list__item">Engineering & Data</div>
|
||||
<div className="skills__list__item">Engineering & Data</div>
|
||||
<div className="skills__list__more">+6</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card-profile__title">Senior Software Engineer</div>
|
||||
<div className="card-profile__subtitle">Auth0</div>
|
||||
<div className="card-profile__desc">
|
||||
I have worked across a variety of organizations, lead teams, and delivered
|
||||
quality software for 8 years. In that time I've worked as an independent
|
||||
consultant, at agencies as a team lead, and as a senior engineer at Auth0. I
|
||||
also host a podcast https://anchor.fm/work-in-programming where I break down how
|
||||
…
|
||||
</div>
|
||||
<div className="card-profile__footer">
|
||||
<a href="#">Details
|
||||
<img className="" src="/images/chevron-forward.svg" alt="" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card-profile">
|
||||
<div className="card-profile__header">
|
||||
<div className="card-profile__header__portrait">
|
||||
<img src="/images/person.png" className="" alt="" />
|
||||
</div>
|
||||
<div className="card-profile__header__inner">
|
||||
<div className="card-profile__header__name">Matthew Weeks</div>
|
||||
<div className="card-profile__header__price">
|
||||
45$ <span>/ 45min</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card-profile__skills">
|
||||
<div className="skills__list">
|
||||
<div className="skills__list__item">Engineering & Data</div>
|
||||
<div className="skills__list__item">Engineering & Data</div>
|
||||
<div className="skills__list__more">+6</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card-profile__title">Senior Software Engineer</div>
|
||||
<div className="card-profile__subtitle">Auth0</div>
|
||||
<div className="card-profile__desc">
|
||||
I have worked across a variety of organizations, lead teams, and delivered
|
||||
quality software for 8 years. In that time I've worked as an independent
|
||||
consultant, at agencies as a team lead, and as a senior engineer at Auth0. I
|
||||
also host a podcast https://anchor.fm/work-in-programming where I break down how
|
||||
…
|
||||
</div>
|
||||
<div className="card-profile__footer">
|
||||
<a href="#">Details
|
||||
<img className="" src="/images/chevron-forward.svg" alt="" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul className="pagination">
|
||||
<li className="page-item"><a className="page-link" href="#">1</a></li>
|
||||
<li className="page-item active" aria-current="page">
|
||||
<a className="page-link" href="#">2</a>
|
||||
</li>
|
||||
<li className="page-item"><a className="page-link" href="#">3</a></li>
|
||||
<li className="page-item"><a className="page-link" href="#">4</a></li>
|
||||
</ul>
|
||||
<ExpertsList data={data} locale={params.locale} />
|
||||
<CustomPagination total={20} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
import { Tabs } from 'antd';
|
||||
|
||||
export const SessionsTabs = ({ intlConfig }: { intlConfig: Record<string, string> }) => {
|
||||
const getChildren = () => (
|
||||
<>
|
||||
<div className="filter-session">
|
||||
<div className="filter-session__item filter-session__item--type">
|
||||
<select name="" id="">
|
||||
<option value="">1</option>
|
||||
<option value="">2</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div className="list-session">
|
||||
<div className="card-profile">
|
||||
<div className="card-profile__header">
|
||||
<div className="card-profile__header__portrait">
|
||||
<img src="/images/person.png" className="" alt="" />
|
||||
</div>
|
||||
<div className="card-profile__header__inner">
|
||||
<div className="card-profile__header__name">Matthew Weeks</div>
|
||||
<div className="card-profile__header__title">
|
||||
Personal Growth Course
|
||||
</div>
|
||||
<div className="card-profile__header__date chosen">
|
||||
Today 10:00 AM - 10:30 AM
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card-profile">
|
||||
<div className="card-profile__header">
|
||||
<div className="card-profile__header__portrait">
|
||||
<img src="/images/person.png" className="" alt="" />
|
||||
</div>
|
||||
<div className="card-profile__header__inner">
|
||||
<div className="card-profile__header__name">Matthew Weeks</div>
|
||||
<div className="card-profile__header__title">
|
||||
Personal Growth Course
|
||||
</div>
|
||||
<div className="card-profile__header__date">
|
||||
8 december at 10:00 AM - 10:30 AM
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card-profile">
|
||||
<div className="card-profile__header">
|
||||
<div className="card-profile__header__portrait">
|
||||
<img src="/images/person.png" className="" alt="" />
|
||||
</div>
|
||||
<div className="card-profile__header__inner">
|
||||
<div className="card-profile__header__name">Matthew Weeks</div>
|
||||
<div className="card-profile__header__title">
|
||||
Personal Growth Course
|
||||
</div>
|
||||
<div className="card-profile__header__date">
|
||||
8 december at 10:00 AM - 10:30 AM
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
const tabs = [
|
||||
{
|
||||
key: 'upcoming',
|
||||
label: (
|
||||
<div className="tabs-session__item active">
|
||||
{intlConfig?.upcoming || 'Tab 1'}
|
||||
<span className="count">3</span>
|
||||
</div>
|
||||
),
|
||||
children: getChildren()
|
||||
},
|
||||
{
|
||||
key: 'requested',
|
||||
label: (
|
||||
<div className="tabs-session__item">
|
||||
{intlConfig?.requested || 'Tab 2'}
|
||||
<span className="count">2</span>
|
||||
</div>
|
||||
),
|
||||
children: getChildren()
|
||||
},
|
||||
{
|
||||
key: 'recent',
|
||||
label: (
|
||||
<div className="tabs-session__item">
|
||||
{intlConfig?.recent || 'Tab 3'}
|
||||
</div>
|
||||
),
|
||||
children: getChildren()
|
||||
}
|
||||
];
|
||||
|
||||
return (
|
||||
<Tabs
|
||||
defaultActiveKey="upcoming"
|
||||
items={tabs}
|
||||
renderTabBar={(props, DefaultTabBar) => (<DefaultTabBar {...props} className="tabs-session" />)}
|
||||
/>
|
||||
);
|
||||
};
|
|
@ -1 +1,2 @@
|
|||
export { AccountMenu } from './AccountMenu';
|
||||
export { SessionsTabs } from './SessionsTabs';
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
'use client';
|
||||
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import { Input, Select } from 'antd';
|
||||
import { Select } from 'antd';
|
||||
import { AdditionalFilter } from '../../types/experts';
|
||||
import { INITIAL_ADD_FILTER } from '../../constants/experts';
|
||||
import { LOCALES } from '../../constants/locale';
|
||||
import { CustomInput } from '../view';
|
||||
|
||||
export const ExpertsAdditionalFilter = () => {
|
||||
const [filter, setFilter] = useState<AdditionalFilter>(INITIAL_ADD_FILTER);
|
||||
|
@ -19,15 +20,20 @@ export const ExpertsAdditionalFilter = () => {
|
|||
return (
|
||||
<div className="main-find__search">
|
||||
<div className="main-find__search__input">
|
||||
<input className="base-input" type="text" placeholder="Search for an Expert" />
|
||||
<CustomInput
|
||||
placeholder="Search for an Expert"
|
||||
onChange={(e: any) => onChangeFilter('text', e?.target?.value)}
|
||||
/>
|
||||
</div>
|
||||
<Input placeholder="Search for an Expert" onChange={(e) => onChangeFilter('text', e?.target?.value)}/>
|
||||
<div className="main-find__search__sort">
|
||||
<Select
|
||||
defaultValue={INITIAL_ADD_FILTER.sort}
|
||||
onChange={(val) => onChangeFilter('sort', val)}
|
||||
options={[
|
||||
{ value: 'By top views', label: 'By top views' }
|
||||
{ value: 'By top views', label: 'By top views' },
|
||||
{ value: 'By Price Ascending', label: 'By Price Ascending' },
|
||||
{ value: 'By Price Descending', label: 'By Price Descending' },
|
||||
{ value: 'By rating', label: 'By rating' }
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,144 @@
|
|||
'use client';
|
||||
|
||||
import React, { FC } from 'react';
|
||||
import Image from 'next/image';
|
||||
import { Tag, Image as AntdImage, Space } from 'antd';
|
||||
import { ZoomInOutlined, ZoomOutOutlined, StarFilled } from '@ant-design/icons';
|
||||
import { ExpertDetails, ExpertDocument } from '../../types/experts';
|
||||
import { Locale } from '../../types/locale';
|
||||
import { CustomRate } from '../view/CustomRate';
|
||||
|
||||
type ExpertDetailsProps = {
|
||||
expert: ExpertDetails;
|
||||
locale?: string;
|
||||
};
|
||||
|
||||
export const ExpertCard: FC<ExpertDetailsProps> = ({ expert }) => {
|
||||
const { publicCoachDetails } = expert || {};
|
||||
|
||||
return (
|
||||
<div className="expert-card">
|
||||
<div className="expert-card__wrap">
|
||||
<div className="expert-card__avatar">
|
||||
<Image src={publicCoachDetails?.faceImageUrl || '/images/person.png'} width={216} height={216} alt="" />
|
||||
</div>
|
||||
<div className="expert-card__inner">
|
||||
<h1 className="expert-card__title">{`${publicCoachDetails?.name} ${publicCoachDetails?.surname || ''}`}</h1>
|
||||
<div className="expert-card__info">
|
||||
<span>{`${publicCoachDetails?.practiceHours} Practice hours`}</span>
|
||||
<i>|</i>
|
||||
<span>{`${publicCoachDetails?.supervisionPerYearId} Supervision per year`}</span>
|
||||
</div>
|
||||
<div className="expert-card__rating">
|
||||
<CustomRate defaultValue={4} character={<StarFilled style={{ fontSize: 32 }} />} disabled />
|
||||
<span>4/5 (out of 345)</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="expert-card__wrap-btn">
|
||||
<a href="#" className="btn-apply">
|
||||
<img src="/images/calendar-outline.svg" className="" alt="" />
|
||||
Schedule
|
||||
</a>
|
||||
<a href="#" className="btn-video">
|
||||
<img src="/images/videocam-outline.svg" className="" alt="" />
|
||||
Video
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const ExpertInformation: FC<ExpertDetailsProps> = ({ expert, locale }) => {
|
||||
const { publicCoachDetails: { tags = [], sessionCost = 0, sessionDuration = 0 } } = expert || {};
|
||||
const isRus = locale === Locale.ru;
|
||||
|
||||
return (
|
||||
<>
|
||||
<h2 className="title-h2">Current Offer</h2>
|
||||
<div className="skills__list">
|
||||
{tags?.map((skill) => <Tag key={skill?.id} className="skills__list__item">{skill?.name}</Tag>)}
|
||||
</div>
|
||||
<p className="base-text">
|
||||
Hello, my name is Marcelo. I am a Senior UX Designer with more than 6 years of experience working
|
||||
with the largest companies in the world such as Disney, Globant and currently IBM.
|
||||
During my career, I have helped organizations solve complex problems using aesthetically pleasing
|
||||
designs with design while building teams and mentoring other designers.
|
||||
I can help you: <br />
|
||||
Prepare for interviews, prepare your resume or CV and work on your LinkedIn profile <br />
|
||||
Get ready for whiteboard challenges and take-home exercises <br />
|
||||
Create a great portfolio and case study presentation. <br />
|
||||
Provide industry information. <br />
|
||||
Professional orientation <br />
|
||||
Strategic thinking <br /><br />
|
||||
|
||||
Oh, and I also speak Spanish!
|
||||
</p>
|
||||
<div className="wrap-btn-prise">
|
||||
<a href="#" className="btn-apply">
|
||||
Sign Up Now
|
||||
</a>
|
||||
<div className="wrap-btn-prise__text">
|
||||
{`${sessionCost}${isRus ? '₽' : '€'}`} <span>/ {`${sessionDuration}${isRus ? 'мин' : 'min'}`}</span>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const ExpertPractice: FC<ExpertDetailsProps> = ({ expert }) => {
|
||||
const { publicCoachDetails: { practiceCases = [], themesGroups = [] } } = expert || {};
|
||||
|
||||
return practiceCases?.length > 0 ? (
|
||||
<div>
|
||||
<h3 className="title-h3">Successful Cases From Practice</h3>
|
||||
{practiceCases?.map(({ id, description, themesGroupIds }) => {
|
||||
const filtered = themesGroups?.filter(({ id }) => themesGroupIds?.includes(+id));
|
||||
|
||||
return (
|
||||
<div key={id} className="case-list">
|
||||
{themesGroupIds && (
|
||||
<div className="skills__list">
|
||||
{filtered?.map(({ id, name }) => (
|
||||
<div key={id} className="skills__list__item">{name}</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
{description && <p className="base-text">{description}</p>}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
) : null;
|
||||
};
|
||||
|
||||
export const ExpertCertificate: FC<{ document: ExpertDocument }> = ({ document }) => (
|
||||
<AntdImage
|
||||
width={160}
|
||||
src={document?.preview?.url}
|
||||
placeholder={(
|
||||
<AntdImage
|
||||
preview={false}
|
||||
src={document?.preview?.url}
|
||||
width={160}
|
||||
fallback="data:image/png;base64,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"
|
||||
/>
|
||||
)}
|
||||
fallback="data:image/png;base64,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"
|
||||
preview={{
|
||||
src: document.fullSize?.url,
|
||||
toolbarRender: (
|
||||
_,
|
||||
{
|
||||
transform: { scale },
|
||||
actions: { onZoomOut, onZoomIn },
|
||||
},
|
||||
) => (
|
||||
<Space size={12} className="toolbar-wrapper">
|
||||
<ZoomOutOutlined disabled={scale === 1} onClick={onZoomOut} />
|
||||
<ZoomInOutlined disabled={scale === 50} onClick={onZoomIn} />
|
||||
</Space>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
);
|
|
@ -0,0 +1,66 @@
|
|||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
import { List, Tag } from 'antd';
|
||||
import { RightOutlined } from '@ant-design/icons';
|
||||
import Image from 'next/image';
|
||||
import { Link } from '../../navigation';
|
||||
import { Locale } from '../../types/locale';
|
||||
import { ExpertsData } from '../../types/experts';
|
||||
|
||||
export const ExpertsList = ({ data, locale }: { data: ExpertsData, locale: string }) => {
|
||||
const isRus = locale === Locale.ru;
|
||||
|
||||
return (
|
||||
<List
|
||||
itemLayout="vertical"
|
||||
size="large"
|
||||
className="search-result"
|
||||
dataSource={data}
|
||||
renderItem={(item) => (
|
||||
<List.Item key={item?.id} className="card-profile">
|
||||
<List.Item.Meta
|
||||
className="card-profile__header"
|
||||
avatar={(
|
||||
<div className="card-profile__header__portrait">
|
||||
<Image src={item?.faceImageUrl || '/images/person.png'} width={100} height={100} alt="" />
|
||||
</div>
|
||||
)}
|
||||
description={(
|
||||
<div className="card-profile__header__inner">
|
||||
<Link href={`/experts/${item?.id}` as any}>
|
||||
<div className="card-profile__header__name">{`${item.name} ${item?.surname || ''}`}</div>
|
||||
</Link>
|
||||
<div className="card-profile__header__price">
|
||||
{`${item?.sessionCost}${isRus ? '₽' : '€'}`} <span>/ {`${item?.sessionDuration}${isRus ? 'мин' : 'min'}`}</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<div className="card-profile__skills">
|
||||
<div className="skills__list">
|
||||
{item?.tags?.slice(0, 2).map((skill) => <Tag key={skill?.id} className="skills__list__item">{skill?.name}</Tag>)}
|
||||
{item?.tags?.length > 2
|
||||
? (
|
||||
<Tag className="skills__list__more">
|
||||
<Link href={`/experts/${item?.id}` as any}>
|
||||
{`+${item?.tags?.length - 2}`}
|
||||
</Link>
|
||||
</Tag>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
<div className="card-profile__title">{item?.speciality}</div>
|
||||
<div className="card-profile__subtitle">{item?.specialityDesc}</div>
|
||||
<div className="card-profile__desc">{item?.description}</div>
|
||||
<div className="card-profile__footer">
|
||||
<Link href={`/experts/${item?.id}` as any}>
|
||||
Details
|
||||
<RightOutlined style={{ fontSize: '10px', padding: '0 7px' }}/>
|
||||
</Link>
|
||||
</div>
|
||||
</List.Item>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
};
|
|
@ -1,77 +1,11 @@
|
|||
'use client';
|
||||
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import { List, Switch, Slider } from 'antd';
|
||||
import styled from 'styled-components';
|
||||
import { List } from 'antd';
|
||||
import { FilterType, INITIAL_FILTER } from '../../constants/experts';
|
||||
import { Filter } from '../../types/experts';
|
||||
|
||||
const CustomSwitch = styled(Switch)`
|
||||
height: 24px !important;
|
||||
background: #F8F8F7 !important;
|
||||
|
||||
.ant-switch-handle {
|
||||
height: 24px !important;
|
||||
width: 24px !important;
|
||||
top: 0 !important;
|
||||
|
||||
&::before {
|
||||
box-shadow: none !important;
|
||||
background: #C4DFE6 !important;
|
||||
border-radius: 50% !important;
|
||||
}
|
||||
}
|
||||
|
||||
&.ant-switch-checked {
|
||||
background: #2c7873 !important;
|
||||
}
|
||||
`;
|
||||
|
||||
const WrapSlider = styled.div`
|
||||
width: 100%;
|
||||
position: relative;
|
||||
margin: 8px 0 16px -5px;
|
||||
`;
|
||||
|
||||
const CustomSlider = styled(Slider)`
|
||||
padding-block: 7px !important;
|
||||
height: 16px !important;
|
||||
|
||||
.ant-slider-rail {
|
||||
background-color: #E5E5E5 !important;
|
||||
}
|
||||
|
||||
.ant-slider-track {
|
||||
background-color: #66A5AD !important;
|
||||
}
|
||||
|
||||
.ant-slider-handle {
|
||||
width: 16px !important;
|
||||
height: 16px !important;
|
||||
|
||||
&::before {
|
||||
width: 16px !important;
|
||||
height: 16px !important;
|
||||
inset-inline-start: 0 !important;
|
||||
inset-block-start: 0 !important;
|
||||
}
|
||||
|
||||
&::after {
|
||||
width: 16px !important;
|
||||
height: 16px !important;
|
||||
background-color: #66A5AD !important;
|
||||
inset-inline-start: 0 !important;
|
||||
inset-block-start: 0 !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
&:focus, &:hover {
|
||||
&::after {
|
||||
box-shadow: 0 0 0 10px rgba(102, 165, 173, .2) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
import { CustomSwitch, CustomSlider } from '../view';
|
||||
import {Locale} from "../../types/locale";
|
||||
|
||||
const dataCoaching = [
|
||||
{
|
||||
|
@ -114,8 +48,9 @@ const dataConsultation = [
|
|||
}
|
||||
];
|
||||
|
||||
export const ExpertsFilter = () => {
|
||||
export const ExpertsFilter = ({ locale }: { locale: string }) => {
|
||||
const [filter, setFilter] = useState<Filter>(INITIAL_FILTER);
|
||||
const isRus = locale === Locale.ru;
|
||||
|
||||
const onChangeFilter = useCallback((key: string, value: any) => {
|
||||
setFilter({
|
||||
|
@ -138,7 +73,7 @@ export const ExpertsFilter = () => {
|
|||
<div className="b-filter__title">{title}</div>
|
||||
<CustomSwitch
|
||||
defaultChecked={filter[key]}
|
||||
onChange={(checked) => onChangeFilter(key, checked)}
|
||||
onChange={(checked: boolean) => onChangeFilter(key, checked)}
|
||||
/>
|
||||
</div>
|
||||
</List.Item>
|
||||
|
@ -155,28 +90,28 @@ export const ExpertsFilter = () => {
|
|||
{getList(dataMentoring)}
|
||||
<h3 className="title-h3">Business-consultation</h3>
|
||||
{getList(dataConsultation)}
|
||||
<h3 className="title-h3">Price from 45€ to 170€</h3>
|
||||
<WrapSlider>
|
||||
<h3 className="title-h3">{`Price from 45${isRus ? '₽' : '€'} to 170${isRus ? '₽' : '€'}`}</h3>
|
||||
<div className="b-filter__slider">
|
||||
<CustomSlider
|
||||
range
|
||||
step={1}
|
||||
defaultValue={INITIAL_FILTER[FilterType.Price]}
|
||||
min={45}
|
||||
max={170}
|
||||
onChange={(val) => onChangeFilter(FilterType.Price, val)}
|
||||
onChange={(val: any) => onChangeFilter(FilterType.Price, val)}
|
||||
/>
|
||||
</WrapSlider>
|
||||
<h3 className="title-h3">Duration from 45m to 120m</h3>
|
||||
<WrapSlider>
|
||||
</div>
|
||||
<h3 className="title-h3">{`Duration from 45${isRus ? 'мин' : 'min'} to 120${isRus ? 'мин' : 'min'}`}</h3>
|
||||
<div className="b-filter__slider">
|
||||
<CustomSlider
|
||||
range
|
||||
step={1}
|
||||
defaultValue={INITIAL_FILTER[FilterType.Duration]}
|
||||
min={45}
|
||||
max={120}
|
||||
onChange={(val) => onChangeFilter(FilterType.Duration, val)}
|
||||
onChange={(val: any) => onChangeFilter(FilterType.Duration, val)}
|
||||
/>
|
||||
</WrapSlider>
|
||||
</div>
|
||||
<button className="btn-apply">Apply</button>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
export * from './Filter';
|
||||
export * from './AdditionalFilter';
|
|
@ -0,0 +1,281 @@
|
|||
'use client';
|
||||
|
||||
import React, { FC, useState } from 'react';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import Image from 'next/image';
|
||||
import {Button, Modal as AntdModal, Form, notification} from 'antd';
|
||||
import { CloseOutlined } from '@ant-design/icons';
|
||||
import { styled } from 'styled-components';
|
||||
import { CustomInput } from '../view';
|
||||
import { getAuth } from '../../actions/auth';
|
||||
|
||||
type AuthModalProps = {
|
||||
open: boolean;
|
||||
handleCancel: () => void;
|
||||
mode: 'enter' | 'register' | 'reset' | 'finish';
|
||||
updateMode: (mode: 'enter' | 'register' | 'reset' | 'finish') => void;
|
||||
};
|
||||
|
||||
const Modal = styled(AntdModal)`
|
||||
.ant-modal-content {
|
||||
border-radius: 24px !important;
|
||||
}
|
||||
|
||||
.ant-modal-close {
|
||||
height: 64px !important;
|
||||
width: 64px !important;
|
||||
border-radius: 50% !important;
|
||||
background: #fff !important;
|
||||
top: -32px !important;
|
||||
inset-inline-end: -32px !important;
|
||||
|
||||
&:active, &:hover {
|
||||
background: #fff !important;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const FilledButton = styled(Button)`
|
||||
background: #66A5AD !important;
|
||||
font-size: 15px !important;
|
||||
border-radius: 8px !important;
|
||||
height: 54px !important;
|
||||
box-shadow: 0px 2px 4px 0px rgba(102, 165, 173, 0.32) !important;
|
||||
`;
|
||||
|
||||
const OutlinedButton = styled(Button)`
|
||||
display: inline-flex !important;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
border-color: #66A5AD !important;
|
||||
color: #66A5AD !important;
|
||||
font-size: 15px !important;
|
||||
border-radius: 8px !important;
|
||||
height: 54px !important;
|
||||
|
||||
span {
|
||||
margin-inline-end: 0 !important;
|
||||
line-height: 15px !important;
|
||||
}
|
||||
`;
|
||||
|
||||
const LinkButton = styled(Button)`
|
||||
color: #66A5AD !important;
|
||||
font-size: 15px !important;
|
||||
height: auto !important;
|
||||
padding: 0 !important;
|
||||
`;
|
||||
|
||||
export const AuthModal: FC<AuthModalProps> = ({
|
||||
open,
|
||||
handleCancel,
|
||||
mode,
|
||||
updateMode
|
||||
}) => {
|
||||
const [form] = Form.useForm<{ login: string, password: string, name: string, surname: string, phone: string }>();
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||
const paths = usePathname().split('/');
|
||||
|
||||
const onAfterClose = () => {
|
||||
form.resetFields();
|
||||
};
|
||||
|
||||
const onSubmit = () => {
|
||||
form.validateFields().then(() => {
|
||||
const { login, password } = form.getFieldsValue();
|
||||
setIsLoading(true);
|
||||
getAuth(login, password, paths[1])
|
||||
.then(({ data }) => {
|
||||
console.log('jwt', data.jwtToken)
|
||||
})
|
||||
.catch((error) => {
|
||||
notification.error({
|
||||
message: 'Error',
|
||||
description: error?.response?.data?.errMessage
|
||||
});
|
||||
})
|
||||
.finally(() => {
|
||||
setIsLoading(false);
|
||||
})
|
||||
});
|
||||
};
|
||||
|
||||
const onValidate = () => {
|
||||
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
open={open}
|
||||
title={undefined}
|
||||
onOk={onSubmit}
|
||||
onCancel={handleCancel}
|
||||
afterClose={onAfterClose}
|
||||
footer={false}
|
||||
width={498}
|
||||
closeIcon={<CloseOutlined style={{ fontSize: 20, color: '#000' }}/>}
|
||||
>
|
||||
<div className="b-modal__auth__content">
|
||||
<div className="b-modal__auth__logo">
|
||||
<img className="" src="/images/logo-auth.svg" alt=""/>
|
||||
</div>
|
||||
{mode === 'enter' && (
|
||||
<>
|
||||
<Form form={form} autoComplete="off" style={{ display: 'flex', gap: 16, flexDirection: 'column' }}>
|
||||
<Form.Item name="login" rules={[{ required: true }]} noStyle>
|
||||
<CustomInput
|
||||
size="small"
|
||||
placeholder="E-mail"
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item name="password" rules={[{ required: true }]} noStyle>
|
||||
<CustomInput
|
||||
size="small"
|
||||
placeholder="Password"
|
||||
type="password"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
<FilledButton
|
||||
type="primary"
|
||||
onClick={onSubmit}
|
||||
loading={isLoading}
|
||||
>
|
||||
Enter
|
||||
</FilledButton>
|
||||
<OutlinedButton onClick={() => updateMode('register')}>Register</OutlinedButton>
|
||||
<LinkButton
|
||||
type="link"
|
||||
onClick={() => updateMode('reset')}
|
||||
>
|
||||
Forgot password?
|
||||
</LinkButton>
|
||||
<span>or</span>
|
||||
<OutlinedButton
|
||||
icon={<Image src="/images/facebook-logo.png" height={20} width={20} alt="" />}
|
||||
>
|
||||
Facebook account
|
||||
</OutlinedButton>
|
||||
<OutlinedButton
|
||||
icon={<Image src="/images/apple-logo.png" height={22} width={22} alt="" />}
|
||||
>
|
||||
Apple account
|
||||
</OutlinedButton>
|
||||
<OutlinedButton
|
||||
icon={<Image src="/images/google-logo.png" height={20} width={20} alt="" />}
|
||||
>
|
||||
Google account
|
||||
</OutlinedButton>
|
||||
</>
|
||||
)}
|
||||
{mode === 'register' && (
|
||||
<>
|
||||
<Form form={form} autoComplete="off" style={{ display: 'flex', gap: 16, flexDirection: 'column' }}>
|
||||
<Form.Item name="name" noStyle>
|
||||
<CustomInput
|
||||
size="small"
|
||||
placeholder="Name"
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item name="surname" noStyle>
|
||||
<CustomInput
|
||||
size="small"
|
||||
placeholder="Surname"
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item name="phone" noStyle>
|
||||
<CustomInput
|
||||
size="small"
|
||||
placeholder="Phone"
|
||||
type="phone"
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item name="login" rules={[{ required: true }]} noStyle>
|
||||
<CustomInput
|
||||
size="small"
|
||||
placeholder="E-mail"
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item name="password" rules={[{ required: true }]} noStyle>
|
||||
<CustomInput
|
||||
size="small"
|
||||
placeholder="Password"
|
||||
type="password"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
<FilledButton
|
||||
type="primary"
|
||||
>
|
||||
Register
|
||||
</FilledButton>
|
||||
<span>or</span>
|
||||
<OutlinedButton
|
||||
icon={<Image src="/images/facebook-logo.png" height={20} width={20} alt="" />}
|
||||
>
|
||||
Facebook account
|
||||
</OutlinedButton>
|
||||
<OutlinedButton
|
||||
icon={<Image src="/images/apple-logo.png" height={22} width={22} alt="" />}
|
||||
>
|
||||
Apple account
|
||||
</OutlinedButton>
|
||||
<OutlinedButton
|
||||
icon={<Image src="/images/google-logo.png" height={20} width={20} alt="" />}
|
||||
>
|
||||
Google account
|
||||
</OutlinedButton>
|
||||
</>
|
||||
)}
|
||||
{mode === 'reset' && (
|
||||
<>
|
||||
<Form form={form} autoComplete="off" style={{ display: 'flex', gap: 16, flexDirection: 'column' }}>
|
||||
<Form.Item name="login" rules={[{ required: true }]} noStyle>
|
||||
<CustomInput
|
||||
size="small"
|
||||
placeholder="E-mail"
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item name="password" rules={[{ required: true }]} noStyle>
|
||||
<CustomInput
|
||||
size="small"
|
||||
placeholder="Password"
|
||||
type="password"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
<FilledButton
|
||||
type="primary"
|
||||
>
|
||||
Reset Password
|
||||
</FilledButton>
|
||||
<LinkButton
|
||||
type="link"
|
||||
>
|
||||
Enter
|
||||
</LinkButton>
|
||||
</>
|
||||
)}
|
||||
{mode === 'finish' && (
|
||||
<>
|
||||
<div className="b-modal__auth__agreement">
|
||||
A link to reset your password has been sent
|
||||
<br />
|
||||
to your email
|
||||
</div>
|
||||
<FilledButton
|
||||
type="primary"
|
||||
>
|
||||
Enter Account
|
||||
</FilledButton>
|
||||
</>
|
||||
)}
|
||||
<div className="b-modal__auth__agreement">
|
||||
I have read and agree with the terms of the
|
||||
User Agreement, Privacy Policy
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
};
|
|
@ -1,24 +1,72 @@
|
|||
import React, { FC } from 'react';
|
||||
import { useTranslations } from 'next-intl';
|
||||
'use client';
|
||||
|
||||
import React, { FC, useState, useEffect } from 'react';
|
||||
import { Button } from 'antd';
|
||||
import { styled } from 'styled-components';
|
||||
import { AuthModal } from '../../Modals/AuthModal';
|
||||
|
||||
type HeaderAuthLinksProps = {
|
||||
enterTitle: string;
|
||||
registerTitle: string;
|
||||
separatorClass?: string;
|
||||
};
|
||||
|
||||
export const HeaderAuthLinks: FC<HeaderAuthLinksProps> = ({ separatorClass = 'b-header__nav__list__line' }) => {
|
||||
const t = useTranslations('Header');
|
||||
const LinkButton = styled(Button)`
|
||||
color: #66A5AD !important;
|
||||
font-size: 16px !important;
|
||||
height: auto !important;
|
||||
padding: 0 !important;
|
||||
font-style: normal !important;
|
||||
font-weight: 600 !important;
|
||||
line-height: normal !important;
|
||||
`;
|
||||
|
||||
export const HeaderAuthLinks: FC<HeaderAuthLinksProps> = ({
|
||||
enterTitle,
|
||||
registerTitle,
|
||||
separatorClass = 'b-header__nav__list__line'
|
||||
}) => {
|
||||
const [isOpenModal, setIsOpenModal] = useState<boolean>(false);
|
||||
const [mode, setMode] = useState<'enter' | 'register' | 'reset' | 'finish'>('enter');
|
||||
|
||||
useEffect(() => {
|
||||
if (!isOpenModal) {
|
||||
setMode('enter');
|
||||
}
|
||||
}, [isOpenModal]);
|
||||
|
||||
const onOpen = (mode: 'enter' | 'register' | 'reset' | 'finish') => {
|
||||
setMode(mode);
|
||||
setIsOpenModal(true);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<li>
|
||||
<a href="#">{t('registration')}</a>
|
||||
<LinkButton
|
||||
type="link"
|
||||
onClick={() => onOpen('register')}
|
||||
>
|
||||
{registerTitle}
|
||||
</LinkButton>
|
||||
</li>
|
||||
<li>
|
||||
<span className={separatorClass}>|</span>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">{t('enter')}</a>
|
||||
<LinkButton
|
||||
type="link"
|
||||
onClick={() => onOpen('enter')}
|
||||
>
|
||||
{enterTitle}
|
||||
</LinkButton>
|
||||
</li>
|
||||
<AuthModal
|
||||
open={isOpenModal}
|
||||
handleCancel={() => setIsOpenModal(false)}
|
||||
mode={mode}
|
||||
updateMode={setMode}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,12 +1,18 @@
|
|||
import React, { ReactNode } from 'react';
|
||||
import { HeaderAuthLinks } from './HeaderAuthLinks';
|
||||
|
||||
export const HeaderMenu = ({ children }: { children: ReactNode }) => (
|
||||
type HeaderMenuProps = {
|
||||
children: ReactNode;
|
||||
enterTitle: string;
|
||||
registerTitle: string;
|
||||
};
|
||||
|
||||
export const HeaderMenu = ({ children, enterTitle, registerTitle }: HeaderMenuProps) => (
|
||||
<div className="b-header__nav">
|
||||
<nav>
|
||||
<ul className="b-header__nav__list ">
|
||||
{children}
|
||||
<HeaderAuthLinks />
|
||||
<HeaderAuthLinks enterTitle={enterTitle} registerTitle={registerTitle} />
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
|
|
@ -5,9 +5,11 @@ import { HeaderAuthLinks } from './HeaderAuthLinks';
|
|||
|
||||
type HeaderMenuMobileProps = {
|
||||
children: ReactNode;
|
||||
enterTitle: string;
|
||||
registerTitle: string;
|
||||
};
|
||||
|
||||
export const HeaderMobileMenu: FC<HeaderMenuMobileProps> = ({ children }) => {
|
||||
export const HeaderMobileMenu: FC<HeaderMenuMobileProps> = ({ children, enterTitle, registerTitle }) => {
|
||||
const [showMobileMenu, setShowMobileMenu] = useState<boolean>(false);
|
||||
|
||||
return (
|
||||
|
@ -27,7 +29,11 @@ export const HeaderMobileMenu: FC<HeaderMenuMobileProps> = ({ children }) => {
|
|||
<img className="img-default" src="/images/avatar.png" alt=""/>
|
||||
</div>
|
||||
<ul className="menu-mobile__header__nav">
|
||||
<HeaderAuthLinks separatorClass="menu-mobile__header__nav__line" />
|
||||
<HeaderAuthLinks
|
||||
separatorClass="menu-mobile__header__nav__line"
|
||||
enterTitle={enterTitle}
|
||||
registerTitle={registerTitle}
|
||||
/>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="menu-mobile__body">
|
||||
|
|
|
@ -23,20 +23,20 @@ export const Header: FC<HeaderProps> = ({ locale }) => {
|
|||
<>
|
||||
<header className="b-header">
|
||||
<div className="b-inner">
|
||||
<div className="b-header__logo">
|
||||
<Link href={'/' as any} className="b-header__logo">
|
||||
<img
|
||||
src="/images/logo-header.svg"
|
||||
className="img-default"
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
<HeaderMenu>
|
||||
</Link>
|
||||
<HeaderMenu enterTitle={t('enter')} registerTitle={t('registration')}>
|
||||
{routes}
|
||||
</HeaderMenu>
|
||||
<LanguageSwitcher locale={locale} />
|
||||
</div>
|
||||
</header>
|
||||
<HeaderMobileMenu>
|
||||
<HeaderMobileMenu enterTitle={t('enter')} registerTitle={t('registration')}>
|
||||
{routes}
|
||||
</HeaderMobileMenu>
|
||||
</>
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { Input as AntdInput } from 'antd';
|
||||
|
||||
const Input = styled(AntdInput)`
|
||||
padding: 15px 16px !important;
|
||||
background: #F8F8F7 !important;
|
||||
border: 1px solid #F8F8F7 !important;
|
||||
border-radius: 8px !important;
|
||||
color: #000 !important;
|
||||
|
||||
&:focus, &:hover {
|
||||
border-color: #66A5AD !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
&::placeholder {
|
||||
color: #000 !important;
|
||||
opacity: .4 !important;
|
||||
}
|
||||
|
||||
&.ant-input-status-error:not(.ant-input-disabled):not(.ant-input-borderless) {
|
||||
border-color: #ff4d4f !important;
|
||||
}
|
||||
`;
|
||||
|
||||
export const CustomInput = (props: any) => (
|
||||
<Input {...props} />
|
||||
);
|
|
@ -0,0 +1,58 @@
|
|||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { Pagination as AntdPagination, PaginationProps } from 'antd';
|
||||
|
||||
const DEFAULT_SIZE = 5;
|
||||
|
||||
const Pagination = styled(AntdPagination)`
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
|
||||
.ant-pagination-item {
|
||||
margin-inline-end: 0 !important;
|
||||
height: 40px !important;
|
||||
width: 40px !important;
|
||||
border-radius: 8px !important;
|
||||
line-height: 38px !important;
|
||||
font-family: var(--font-inter) !important;
|
||||
font-weight: 400 !important;
|
||||
border-color: #2c7873 !important;
|
||||
font-size: 16px !important;
|
||||
|
||||
a {
|
||||
color: #2c7873 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-pagination-item-active {
|
||||
background: #2c7873 !important;
|
||||
|
||||
a {
|
||||
color: #fff !important;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-pagination-item:not(.ant-pagination-item-active):active,
|
||||
.ant-pagination-item:not(.ant-pagination-item-active):hover {
|
||||
background-color: rgba(44, 120, 115, 0.06) !important;
|
||||
}
|
||||
`;
|
||||
|
||||
const itemRender: PaginationProps['itemRender'] = (_, type, originalElement) => {
|
||||
if (type === 'prev' || type === 'next') {
|
||||
return null;
|
||||
}
|
||||
|
||||
return originalElement;
|
||||
};
|
||||
|
||||
export const CustomPagination = (props: PaginationProps) => (
|
||||
<Pagination
|
||||
itemRender={itemRender}
|
||||
defaultCurrent={1}
|
||||
defaultPageSize={DEFAULT_SIZE}
|
||||
{...props}
|
||||
/>
|
||||
);
|
|
@ -0,0 +1,25 @@
|
|||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { Rate as AntdRate } from 'antd';
|
||||
|
||||
const Rate = styled(AntdRate)`
|
||||
display: inline-flex !important;
|
||||
gap: 4px;
|
||||
|
||||
li {
|
||||
margin-inline-end: 0 !important;
|
||||
padding: 5px 0 0 !important;
|
||||
|
||||
&.ant-rate-star-full span {
|
||||
color: #ffbd00 !important;
|
||||
}
|
||||
|
||||
&.ant-rate-star-zero span {
|
||||
color: #c4dfe6 !important;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const CustomRate = (props: any) => (
|
||||
<Rate {...props} />
|
||||
);
|
|
@ -0,0 +1,49 @@
|
|||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { Slider as AntdSlider } from 'antd';
|
||||
|
||||
const Slider = styled(AntdSlider)`
|
||||
padding-block: 7px !important;
|
||||
height: 16px !important;
|
||||
|
||||
.ant-slider-rail {
|
||||
background-color: #E5E5E5 !important;
|
||||
}
|
||||
|
||||
.ant-slider-track {
|
||||
background-color: #66A5AD !important;
|
||||
}
|
||||
|
||||
.ant-slider-handle {
|
||||
width: 16px !important;
|
||||
height: 16px !important;
|
||||
|
||||
&::before {
|
||||
width: 16px !important;
|
||||
height: 16px !important;
|
||||
inset-inline-start: 0 !important;
|
||||
inset-block-start: 0 !important;
|
||||
}
|
||||
|
||||
&::after {
|
||||
width: 16px !important;
|
||||
height: 16px !important;
|
||||
background-color: #66A5AD !important;
|
||||
inset-inline-start: 0 !important;
|
||||
inset-block-start: 0 !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
&:focus, &:hover {
|
||||
&::after {
|
||||
box-shadow: 0 0 0 10px rgba(102, 165, 173, .2) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const CustomSlider = (props: any) => (
|
||||
<Slider {...props} />
|
||||
);
|
|
@ -0,0 +1,34 @@
|
|||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { Switch as AntdSwitch } from 'antd';
|
||||
|
||||
const Switch = styled(AntdSwitch)`
|
||||
height: 24px !important;
|
||||
background: #F8F8F7 !important;
|
||||
|
||||
.ant-switch-handle {
|
||||
height: 24px !important;
|
||||
width: 24px !important;
|
||||
top: 0 !important;
|
||||
|
||||
&::before {
|
||||
box-shadow: none !important;
|
||||
background: #C4DFE6 !important;
|
||||
border-radius: 50% !important;
|
||||
}
|
||||
}
|
||||
|
||||
&.ant-switch-checked {
|
||||
background: #F8F8F7 !important;
|
||||
|
||||
.ant-switch-handle::before {
|
||||
background: #66A5AD !important;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const CustomSwitch = (props: any) => (
|
||||
<Switch {...props} />
|
||||
);
|
|
@ -0,0 +1,7 @@
|
|||
'use client';
|
||||
|
||||
export * from './CustomSwitch';
|
||||
export * from './CustomSlider';
|
||||
export * from './CustomPagination';
|
||||
export * from './CustomRate';
|
||||
export * from './CustomInput';
|
|
@ -0,0 +1 @@
|
|||
export const BASE_URL = process.env.NEXT_PUBLIC_SERVER_BASE_URL || 'https://api.bbuddy.expert/api';
|
|
@ -0,0 +1,33 @@
|
|||
import axios, { InternalAxiosRequestConfig, AxiosResponse } from 'axios';
|
||||
import { BASE_URL } from '../constants/common';
|
||||
// import { getAuthToken } from '../../utils';
|
||||
|
||||
export const onSuccessRequestCallback = (config: InternalAxiosRequestConfig) => {
|
||||
const newConfig = { ...config };
|
||||
|
||||
// if (!newConfig.headers) {
|
||||
// newConfig.headers = {};
|
||||
// }
|
||||
//
|
||||
// if (IS_DEV && !newConfig.headers.Authorization && getAuthToken()) {
|
||||
// newConfig.headers.Authorization = `Bearer ${getAuthToken()}`;
|
||||
// }
|
||||
newConfig.headers['Content-Type'] = 'application/json';
|
||||
|
||||
return newConfig;
|
||||
};
|
||||
|
||||
export const onSuccessResponseCallback = (response: AxiosResponse) => response;
|
||||
|
||||
export const onErrorResponseCallback = (error: any) => Promise.reject(error);
|
||||
|
||||
export const apiClient = axios.create({
|
||||
baseURL: BASE_URL
|
||||
});
|
||||
|
||||
apiClient.interceptors.request.use(onSuccessRequestCallback);
|
||||
|
||||
apiClient.interceptors.response.use(
|
||||
onSuccessResponseCallback,
|
||||
onErrorResponseCallback
|
||||
);
|
|
@ -9,4 +9,5 @@ export default createMiddleware({
|
|||
|
||||
export const config = {
|
||||
matcher: ['/', '/(en|ru|de|it|es|fr)/:path*']
|
||||
// matcher: ['/', '/(en|ru|de|it|es|fr).html']
|
||||
};
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
.b {
|
||||
&-modal {
|
||||
&__auth {
|
||||
&__content {
|
||||
padding: 80px 76px 68px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
text-align: center;
|
||||
|
||||
span, div {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
& > span {
|
||||
color: #66A5AD;
|
||||
}
|
||||
}
|
||||
|
||||
&__logo {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
&__agreement {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,6 +10,10 @@ body{
|
|||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
*::selection {
|
||||
background-color: #2C7873;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.b-wrapper {
|
||||
width: 100%;
|
||||
|
@ -305,6 +309,12 @@ body{
|
|||
gap: 16px;
|
||||
}
|
||||
|
||||
&__slider {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
margin: 8px 0 16px -5px;
|
||||
}
|
||||
|
||||
&__title {
|
||||
color: $black;
|
||||
@include rem(15);
|
||||
|
@ -480,18 +490,20 @@ body{
|
|||
|
||||
//
|
||||
.card-profile {
|
||||
display: flex;
|
||||
display: flex !important;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 1px solid #C4DFE6;
|
||||
gap: 8px !important;
|
||||
padding: 0 0 8px !important;
|
||||
border-block-end: 1px solid #C4DFE6 !important;
|
||||
margin: 0 0 16px !important;
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
padding-bottom: 8px;
|
||||
align-items: center;
|
||||
align-items: center !important;
|
||||
gap: 16px;
|
||||
align-self: stretch;
|
||||
margin-block-end: 0 !important;
|
||||
|
||||
&__portrait {
|
||||
width: 86px;
|
||||
|
@ -499,8 +511,9 @@ body{
|
|||
border-radius: 16px;
|
||||
border: 2px solid #FFF;
|
||||
background: lightgray 50%;
|
||||
box-shadow: 0px 8px 16px 0px rgba(102, 165, 173, 0.32);
|
||||
box-shadow: 0 8px 16px 0 rgba(102, 165, 173, 0.32);
|
||||
overflow: hidden;
|
||||
margin-right: -16px;
|
||||
|
||||
img {
|
||||
object-fit: cover;
|
||||
|
@ -599,70 +612,29 @@ body{
|
|||
align-self: stretch;
|
||||
|
||||
&__item {
|
||||
height: 22px;
|
||||
border-radius: 4px;
|
||||
background: #2C7873;
|
||||
display: inline-flex;
|
||||
padding: 4px;
|
||||
color: #FFF;
|
||||
@include rem(12);
|
||||
margin-inline-end: 0 !important;
|
||||
padding-inline: 4px !important;
|
||||
font-size: 0.75rem;
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
line-height: 116.667%;
|
||||
align-items: center;
|
||||
line-height: 20px;
|
||||
background: #2C7873 !important;
|
||||
border-color: #2C7873 !important;
|
||||
color: #fff !important;
|
||||
height: 22px;
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
&__more {
|
||||
height: 22px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 4px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #2C7873;
|
||||
color: #2C7873;
|
||||
@include rem(12);
|
||||
margin-inline-end: 0 !important;
|
||||
padding-inline: 4px !important;
|
||||
font-size: 0.75rem;
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
line-height: 116.667%;
|
||||
}
|
||||
}
|
||||
|
||||
.pagination {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
|
||||
.page-item {
|
||||
border-radius: 8px;
|
||||
display: inline-flex;
|
||||
height: 40px;
|
||||
width: 40px;
|
||||
|
||||
.page-link {
|
||||
border-radius: 8px;
|
||||
border: 1px solid #2C7873;
|
||||
display: inline-flex;
|
||||
padding: 8px 16px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: $white;
|
||||
height: 40px;
|
||||
width: 40px;
|
||||
color: #2C7873;
|
||||
text-align: center;
|
||||
font-family: 'Inter', sans-serif;
|
||||
@include rem(16);
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 150%;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
&.active {
|
||||
.page-link {
|
||||
background: #2C7873;
|
||||
color: $white;
|
||||
}
|
||||
}
|
||||
line-height: 22px;
|
||||
border-color: #2C7873 !important;
|
||||
color: #2C7873 !important;
|
||||
height: 22px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -740,17 +712,17 @@ body{
|
|||
|
||||
&__rating {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
flex-flow: wrap;
|
||||
|
||||
span {
|
||||
& > span {
|
||||
display: block;
|
||||
color: #2C7873;
|
||||
@include rem(13);
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 123.077%;
|
||||
padding-top: 9px;
|
||||
}
|
||||
|
||||
img {
|
||||
|
|
|
@ -610,10 +610,3 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.search-result {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
|
|
@ -9,5 +9,6 @@
|
|||
@import "_pages.scss";
|
||||
@import "_form.scss";
|
||||
@import "_message.scss";
|
||||
@import "_auth-modal.scss";
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,108 @@
|
|||
export type Filter = Record<string, any>;
|
||||
|
||||
// export type Filter = {
|
||||
// themesTagIds: number[];
|
||||
// priceFrom?: number | null;
|
||||
// priceTo?: number | null;
|
||||
// durationFrom?: number | null;
|
||||
// durationTo?: number | null;
|
||||
// };
|
||||
|
||||
export type AdditionalFilter = {
|
||||
text?: string;
|
||||
sort?: string;
|
||||
language?: string[];
|
||||
};
|
||||
|
||||
export type Tag = {
|
||||
id: number;
|
||||
groupId: number;
|
||||
name: string
|
||||
couchCount?: number;
|
||||
group?: string | null;
|
||||
};
|
||||
|
||||
export type File = {
|
||||
id: number;
|
||||
fileType: string;
|
||||
url: string;
|
||||
};
|
||||
|
||||
export interface ExpertDocument {
|
||||
fileName: string;
|
||||
original?: File;
|
||||
preview?: File;
|
||||
fullSize?: File;
|
||||
}
|
||||
|
||||
export type Details = {
|
||||
id: number;
|
||||
userId?:number;
|
||||
title?: string;
|
||||
description?: string;
|
||||
document?: ExpertDocument;
|
||||
};
|
||||
|
||||
export type Certificate = {
|
||||
id: number;
|
||||
userId?: number;
|
||||
associationLevelId?: number;
|
||||
document?: ExpertDocument;
|
||||
};
|
||||
|
||||
export type Practice = {
|
||||
id: number;
|
||||
userId?: number;
|
||||
description?: string;
|
||||
themesGroupIds?: number[];
|
||||
};
|
||||
|
||||
export type ThemeGroup = {
|
||||
id: number;
|
||||
name: string;
|
||||
isActive?: boolean;
|
||||
canDeleted?: boolean;
|
||||
};
|
||||
|
||||
export type Association = {
|
||||
id: number;
|
||||
name: string;
|
||||
};
|
||||
|
||||
export type AssociationLevel = {
|
||||
id: number;
|
||||
associationId: number;
|
||||
name: string;
|
||||
};
|
||||
|
||||
export interface ExpertItem {
|
||||
id: number;
|
||||
name: string;
|
||||
surname?: string;
|
||||
faceImageUrl?: string;
|
||||
sessionDuration: number;
|
||||
sessionCost: number;
|
||||
coachRating?: number;
|
||||
tags: Tag[];
|
||||
speciality?: string;
|
||||
specialityDesc?: string;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
export type ExpertsData = ExpertItem[];
|
||||
|
||||
export type ExpertDetails = {
|
||||
publicCoachDetails: ExpertItem & {
|
||||
practiceHours?: number;
|
||||
supervisionPerYearId?: number;
|
||||
educations?: Details[];
|
||||
certificates?: Certificate[];
|
||||
trainings?: Details[];
|
||||
mbas?: Details[];
|
||||
experiences?: Details[];
|
||||
practiceCases?: Practice[];
|
||||
themesGroups?: ThemeGroup[];
|
||||
};
|
||||
associations?: Association[];
|
||||
associationLevels?: AssociationLevel[];
|
||||
};
|
||||
|
|
|
@ -29,7 +29,8 @@
|
|||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
".next/types/**/*.ts",
|
||||
"dist/types/**/*.ts"
|
||||
"dist/types/**/*.ts",
|
||||
"build/types/**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
|
|