feat: add new static pages
|
@ -2,15 +2,31 @@
|
|||
"Header": {
|
||||
"registration": "Registration",
|
||||
"enter": "Enter",
|
||||
"account": "My Account",
|
||||
"menu": {
|
||||
"faq": "Start grow with BB",
|
||||
"experts": "Become BB Expert",
|
||||
"news": "Blog&News"
|
||||
"bb-client": "Start grow with BB",
|
||||
"bb-expert": "Become BB Expert",
|
||||
"blog": "Blog&News"
|
||||
}
|
||||
},
|
||||
"Main": {
|
||||
"title": "Bbuddy - Main",
|
||||
"description": "Bbuddy desc"
|
||||
"description": "Bbuddy desc",
|
||||
"header": "Mentorship, Career\nDevelopment & Coaching.",
|
||||
"header-desc": "The ins-and-outs of building a career in tech, gaining experience from a mentor, and getting your feet wet with coaching.",
|
||||
"news": "Professional Articles & Project News",
|
||||
"popular": "Popular Topics"
|
||||
},
|
||||
"BbClient": {
|
||||
"title": "Bbuddy - Client",
|
||||
"description": "Bbuddy desc client",
|
||||
"header": "Personal, professional, and business\ndevelopment mobile application"
|
||||
},
|
||||
"BbExpert": {
|
||||
"title": "Bbuddy - Expert",
|
||||
"description": "Bbuddy desc expert",
|
||||
"header": "Be where your customers are",
|
||||
"header-desc": "B Buddy is an application for active people interested in growth on all fronts — personal, professional and business. Right now they are looking for you."
|
||||
},
|
||||
"Account": {
|
||||
"menu": {
|
||||
|
@ -71,5 +87,22 @@
|
|||
"faq": "FAQ",
|
||||
"privacy-policy": "Privacy Policy"
|
||||
}
|
||||
},
|
||||
"Experts": {
|
||||
"title": "Find a expert",
|
||||
"filter": {
|
||||
"price": "Price from {from}€ to {to}€",
|
||||
"duration": "Duration from {from}min to {to}min",
|
||||
"apply": "Apply",
|
||||
"find": "Find",
|
||||
"search": "Search for an Expert",
|
||||
"sort": "Sort",
|
||||
"language": "Language"
|
||||
},
|
||||
"list": {
|
||||
"price": "0€",
|
||||
"duration": "0min",
|
||||
"details": "Details"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,16 +2,31 @@
|
|||
"Header": {
|
||||
"registration": "Registration",
|
||||
"enter": "Enter",
|
||||
"account": "My Account",
|
||||
"menu": {
|
||||
"faq": "Start grow with BB",
|
||||
"experts": "Become BB Expert",
|
||||
"news": "Blog&News"
|
||||
"bb-client": "Start grow with BB",
|
||||
"bb-expert": "Become BB Expert",
|
||||
"blog": "Blog&News"
|
||||
}
|
||||
},
|
||||
"Main": {
|
||||
"title": "Bbuddy - Main",
|
||||
"description": "Bbuddy desc",
|
||||
"news": "Professional Articles & Project News"
|
||||
"header": "Mentorship, Career\nDevelopment & Coaching.",
|
||||
"header-desc": "The ins-and-outs of building a career in tech, gaining experience from a mentor, and getting your feet wet with coaching.",
|
||||
"news": "Professional Articles & Project News",
|
||||
"popular": "Popular Topics"
|
||||
},
|
||||
"BbClient": {
|
||||
"title": "Bbuddy - Client",
|
||||
"description": "Bbuddy desc client",
|
||||
"header": "Personal, professional, and business\ndevelopment mobile application"
|
||||
},
|
||||
"BbExpert": {
|
||||
"title": "Bbuddy - Expert",
|
||||
"description": "Bbuddy desc expert",
|
||||
"header": "Be where your customers are",
|
||||
"header-desc": "B Buddy is an application for active people interested in growth on all fronts — personal, professional and business. Right now they are looking for you."
|
||||
},
|
||||
"Account": {
|
||||
"menu": {
|
||||
|
@ -72,5 +87,22 @@
|
|||
"faq": "FAQ",
|
||||
"privacy-policy": "Privacy Policy"
|
||||
}
|
||||
},
|
||||
"Experts": {
|
||||
"title": "Find a expert",
|
||||
"filter": {
|
||||
"price": "Price from {from}€ to {to}€",
|
||||
"duration": "Duration from {from}min to {to}min",
|
||||
"apply": "Apply",
|
||||
"find": "Find",
|
||||
"search": "Search for an Expert",
|
||||
"sort": "Sort",
|
||||
"language": "Language"
|
||||
},
|
||||
"list": {
|
||||
"price": "0€",
|
||||
"duration": "0min",
|
||||
"details": "Details"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,15 +2,31 @@
|
|||
"Header": {
|
||||
"registration": "Registration",
|
||||
"enter": "Enter",
|
||||
"account": "My Account",
|
||||
"menu": {
|
||||
"faq": "Start grow with BB",
|
||||
"experts": "Become BB Expert",
|
||||
"news": "Blog&News"
|
||||
"bb-client": "Start grow with BB",
|
||||
"bb-expert": "Become BB Expert",
|
||||
"blog": "Blog&News"
|
||||
}
|
||||
},
|
||||
"Main": {
|
||||
"title": "Bbuddy - Main",
|
||||
"description": "Bbuddy desc"
|
||||
"description": "Bbuddy desc",
|
||||
"header": "Mentorship, Career\nDevelopment & Coaching.",
|
||||
"header-desc": "The ins-and-outs of building a career in tech, gaining experience from a mentor, and getting your feet wet with coaching.",
|
||||
"news": "Professional Articles & Project News",
|
||||
"popular": "Popular Topics"
|
||||
},
|
||||
"BbClient": {
|
||||
"title": "Bbuddy - Client",
|
||||
"description": "Bbuddy desc client",
|
||||
"header": "Personal, professional, and business\ndevelopment mobile application"
|
||||
},
|
||||
"BbExpert": {
|
||||
"title": "Bbuddy - Expert",
|
||||
"description": "Bbuddy desc expert",
|
||||
"header": "Be where your customers are",
|
||||
"header-desc": "B Buddy is an application for active people interested in growth on all fronts — personal, professional and business. Right now they are looking for you."
|
||||
},
|
||||
"Account": {
|
||||
"menu": {
|
||||
|
@ -71,5 +87,22 @@
|
|||
"faq": "FAQ",
|
||||
"privacy-policy": "Privacy Policy"
|
||||
}
|
||||
},
|
||||
"Experts": {
|
||||
"title": "Find a expert",
|
||||
"filter": {
|
||||
"price": "Price from {from}€ to {to}€",
|
||||
"duration": "Duration from {from}min to {to}min",
|
||||
"apply": "Apply",
|
||||
"find": "Find",
|
||||
"search": "Search for an Expert",
|
||||
"sort": "Sort",
|
||||
"language": "Language"
|
||||
},
|
||||
"list": {
|
||||
"price": "0€",
|
||||
"duration": "0min",
|
||||
"details": "Details"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,15 +2,31 @@
|
|||
"Header": {
|
||||
"registration": "Registration",
|
||||
"enter": "Enter",
|
||||
"account": "My Account",
|
||||
"menu": {
|
||||
"faq": "Start grow with BB",
|
||||
"experts": "Become BB Expert",
|
||||
"news": "Blog&News"
|
||||
"bb-client": "Start grow with BB",
|
||||
"bb-expert": "Become BB Expert",
|
||||
"blog": "Blog&News"
|
||||
}
|
||||
},
|
||||
"Main": {
|
||||
"title": "Bbuddy - Main",
|
||||
"description": "Bbuddy desc"
|
||||
"description": "Bbuddy desc",
|
||||
"header": "Mentorship, Career\nDevelopment & Coaching.",
|
||||
"header-desc": "The ins-and-outs of building a career in tech, gaining experience from a mentor, and getting your feet wet with coaching.",
|
||||
"news": "Professional Articles & Project News",
|
||||
"popular": "Popular Topics"
|
||||
},
|
||||
"BbClient": {
|
||||
"title": "Bbuddy - Client",
|
||||
"description": "Bbuddy desc client",
|
||||
"header": "Personal, professional, and business\ndevelopment mobile application"
|
||||
},
|
||||
"BbExpert": {
|
||||
"title": "Bbuddy - Expert",
|
||||
"description": "Bbuddy desc expert",
|
||||
"header": "Be where your customers are",
|
||||
"header-desc": "B Buddy is an application for active people interested in growth on all fronts — personal, professional and business. Right now they are looking for you."
|
||||
},
|
||||
"Account": {
|
||||
"menu": {
|
||||
|
@ -71,5 +87,22 @@
|
|||
"faq": "FAQ",
|
||||
"privacy-policy": "Privacy Policy"
|
||||
}
|
||||
},
|
||||
"Experts": {
|
||||
"title": "Find a expert",
|
||||
"filter": {
|
||||
"price": "Price from {from}€ to {to}€",
|
||||
"duration": "Duration from {from}min to {to}min",
|
||||
"apply": "Apply",
|
||||
"find": "Find",
|
||||
"search": "Search for an Expert",
|
||||
"sort": "Sort",
|
||||
"language": "Language"
|
||||
},
|
||||
"list": {
|
||||
"price": "0€",
|
||||
"duration": "0min",
|
||||
"details": "Details"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,15 +2,31 @@
|
|||
"Header": {
|
||||
"registration": "Registration",
|
||||
"enter": "Enter",
|
||||
"account": "My Account",
|
||||
"menu": {
|
||||
"faq": "Start grow with BB",
|
||||
"experts": "Become BB Expert",
|
||||
"news": "Blog&News"
|
||||
"bb-client": "Start grow with BB",
|
||||
"bb-expert": "Become BB Expert",
|
||||
"blog": "Blog&News"
|
||||
}
|
||||
},
|
||||
"Main": {
|
||||
"title": "Bbuddy - Main",
|
||||
"description": "Bbuddy desc"
|
||||
"description": "Bbuddy desc",
|
||||
"header": "Mentorship, Career\nDevelopment & Coaching.",
|
||||
"header-desc": "The ins-and-outs of building a career in tech, gaining experience from a mentor, and getting your feet wet with coaching.",
|
||||
"news": "Professional Articles & Project News",
|
||||
"popular": "Popular Topics"
|
||||
},
|
||||
"BbClient": {
|
||||
"title": "Bbuddy - Client",
|
||||
"description": "Bbuddy desc client",
|
||||
"header": "Personal, professional, and business\ndevelopment mobile application"
|
||||
},
|
||||
"BbExpert": {
|
||||
"title": "Bbuddy - Expert",
|
||||
"description": "Bbuddy desc expert",
|
||||
"header": "Be where your customers are",
|
||||
"header-desc": "B Buddy is an application for active people interested in growth on all fronts — personal, professional and business. Right now they are looking for you."
|
||||
},
|
||||
"Account": {
|
||||
"menu": {
|
||||
|
@ -71,5 +87,22 @@
|
|||
"faq": "FAQ",
|
||||
"privacy-policy": "Privacy Policy"
|
||||
}
|
||||
},
|
||||
"Experts": {
|
||||
"title": "Find a expert",
|
||||
"filter": {
|
||||
"price": "Price from {from}€ to {to}€",
|
||||
"duration": "Duration from {from}min to {to}min",
|
||||
"apply": "Apply",
|
||||
"find": "Find",
|
||||
"search": "Search for an Expert",
|
||||
"sort": "Sort",
|
||||
"language": "Language"
|
||||
},
|
||||
"list": {
|
||||
"price": "0€",
|
||||
"duration": "0min",
|
||||
"details": "Details"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,15 +2,31 @@
|
|||
"Header": {
|
||||
"registration": "Регистрация",
|
||||
"enter": "Вход",
|
||||
"account": "Мой аккаунт",
|
||||
"menu": {
|
||||
"faq": "Начни вместе с BB",
|
||||
"experts": "Стань BB экспертом",
|
||||
"news": "Блог&Новости"
|
||||
"bb-client": "Начни вместе с BB",
|
||||
"bb-expert": "Стань BB экспертом",
|
||||
"blog": "Блог&Новости"
|
||||
}
|
||||
},
|
||||
"Main": {
|
||||
"title": "Bbuddy - Главная",
|
||||
"description": "Bbuddy описание"
|
||||
"description": "Bbuddy описание",
|
||||
"header": "Mentorship, Career\nDevelopment & Coaching.",
|
||||
"header-desc": "The ins-and-outs of building a career in tech, gaining experience from a mentor, and getting your feet wet with coaching.",
|
||||
"news": "Professional Articles & Project News",
|
||||
"popular": "Popular Topics"
|
||||
},
|
||||
"BbClient": {
|
||||
"title": "Bbuddy - Client",
|
||||
"description": "Bbuddy desc client",
|
||||
"header": "Personal, professional, and business\ndevelopment mobile application"
|
||||
},
|
||||
"BbExpert": {
|
||||
"title": "Bbuddy - Expert",
|
||||
"description": "Bbuddy desc expert",
|
||||
"header": "Be where your customers are",
|
||||
"header-desc": "B Buddy is an application for active people interested in growth on all fronts — personal, professional and business. Right now they are looking for you."
|
||||
},
|
||||
"Account": {
|
||||
"menu": {
|
||||
|
@ -71,5 +87,22 @@
|
|||
"faq": "Помощь",
|
||||
"privacy-policy": "Политика конфиденциальности"
|
||||
}
|
||||
},
|
||||
"Experts": {
|
||||
"title": "Найти эксперта",
|
||||
"filter": {
|
||||
"price": "Цена от {from}₽ до {to}₽",
|
||||
"duration": "Продолжительность от {from}мин до {to}мин",
|
||||
"apply": "Применить",
|
||||
"find": "Найти",
|
||||
"search": "Поиск",
|
||||
"sort": "Сортировка",
|
||||
"language": "Язык"
|
||||
},
|
||||
"list": {
|
||||
"price": "0₽",
|
||||
"duration": "0мин",
|
||||
"details": "Детали"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,22 +19,13 @@ const nextConfig = {
|
|||
},
|
||||
experimental: {
|
||||
taint: true,
|
||||
typedRoutes: true
|
||||
// typedRoutes: true
|
||||
},
|
||||
output: 'export',
|
||||
distDir: 'dist',
|
||||
poweredByHeader: false,
|
||||
productionBrowserSourceMaps: true,
|
||||
trailingSlash: true
|
||||
// redirects: async () => {
|
||||
// return [
|
||||
// {
|
||||
// source: '/en/',
|
||||
// destination: '/en.html',
|
||||
// permanent: true
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
};
|
||||
|
||||
module.exports = withNextIntl(nextConfig);
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
"next-intl": "^3.3.1",
|
||||
"react": "^18",
|
||||
"react-dom": "^18",
|
||||
"react-slick": "^0.29.0",
|
||||
"slick-carousel": "^1.8.1",
|
||||
"styled-components": "^6.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -1617,6 +1619,11 @@
|
|||
"node": ">=10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/enquire.js": {
|
||||
"version": "2.1.6",
|
||||
"resolved": "https://registry.npmjs.org/enquire.js/-/enquire.js-2.1.6.tgz",
|
||||
"integrity": "sha512-/KujNpO+PT63F7Hlpu4h3pE3TokKRHN26JYmQpPyjkRD/N57R7bPDNojMXdi7uveAKjYB7yQnartCxZnFWr0Xw=="
|
||||
},
|
||||
"node_modules/es-abstract": {
|
||||
"version": "1.22.3",
|
||||
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz",
|
||||
|
@ -3071,6 +3078,12 @@
|
|||
"set-function-name": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/jquery": {
|
||||
"version": "3.7.1",
|
||||
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz",
|
||||
"integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
|
@ -3196,6 +3209,11 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash.debounce": {
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
|
||||
"integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="
|
||||
},
|
||||
"node_modules/lodash.merge": {
|
||||
"version": "4.6.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
||||
|
@ -4356,6 +4374,22 @@
|
|||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/react-slick": {
|
||||
"version": "0.29.0",
|
||||
"resolved": "https://registry.npmjs.org/react-slick/-/react-slick-0.29.0.tgz",
|
||||
"integrity": "sha512-TGdOKE+ZkJHHeC4aaoH85m8RnFyWqdqRfAGkhd6dirmATXMZWAxOpTLmw2Ll/jPTQ3eEG7ercFr/sbzdeYCJXA==",
|
||||
"dependencies": {
|
||||
"classnames": "^2.2.5",
|
||||
"enquire.js": "^2.1.6",
|
||||
"json2mq": "^0.2.0",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"resize-observer-polyfill": "^1.5.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0",
|
||||
"react-dom": "^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/readdirp": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||
|
@ -4656,6 +4690,14 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/slick-carousel": {
|
||||
"version": "1.8.1",
|
||||
"resolved": "https://registry.npmjs.org/slick-carousel/-/slick-carousel-1.8.1.tgz",
|
||||
"integrity": "sha512-XB9Ftrf2EEKfzoQXt3Nitrt/IPbT+f1fgqBdoxO3W/+JYvtEOW6EgxnWfr9GH6nmULv7Y2tPmEX3koxThVmebA==",
|
||||
"peerDependencies": {
|
||||
"jquery": ">=1.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map-js": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
|
||||
|
@ -6376,6 +6418,11 @@
|
|||
"tapable": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"enquire.js": {
|
||||
"version": "2.1.6",
|
||||
"resolved": "https://registry.npmjs.org/enquire.js/-/enquire.js-2.1.6.tgz",
|
||||
"integrity": "sha512-/KujNpO+PT63F7Hlpu4h3pE3TokKRHN26JYmQpPyjkRD/N57R7bPDNojMXdi7uveAKjYB7yQnartCxZnFWr0Xw=="
|
||||
},
|
||||
"es-abstract": {
|
||||
"version": "1.22.3",
|
||||
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz",
|
||||
|
@ -7449,6 +7496,12 @@
|
|||
"set-function-name": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"jquery": {
|
||||
"version": "3.7.1",
|
||||
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz",
|
||||
"integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==",
|
||||
"peer": true
|
||||
},
|
||||
"js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
|
@ -7553,6 +7606,11 @@
|
|||
"p-locate": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"lodash.debounce": {
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
|
||||
"integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="
|
||||
},
|
||||
"lodash.merge": {
|
||||
"version": "4.6.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
||||
|
@ -8337,6 +8395,18 @@
|
|||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
||||
"dev": true
|
||||
},
|
||||
"react-slick": {
|
||||
"version": "0.29.0",
|
||||
"resolved": "https://registry.npmjs.org/react-slick/-/react-slick-0.29.0.tgz",
|
||||
"integrity": "sha512-TGdOKE+ZkJHHeC4aaoH85m8RnFyWqdqRfAGkhd6dirmATXMZWAxOpTLmw2Ll/jPTQ3eEG7ercFr/sbzdeYCJXA==",
|
||||
"requires": {
|
||||
"classnames": "^2.2.5",
|
||||
"enquire.js": "^2.1.6",
|
||||
"json2mq": "^0.2.0",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"resize-observer-polyfill": "^1.5.0"
|
||||
}
|
||||
},
|
||||
"readdirp": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||
|
@ -8547,6 +8617,12 @@
|
|||
"integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
|
||||
"dev": true
|
||||
},
|
||||
"slick-carousel": {
|
||||
"version": "1.8.1",
|
||||
"resolved": "https://registry.npmjs.org/slick-carousel/-/slick-carousel-1.8.1.tgz",
|
||||
"integrity": "sha512-XB9Ftrf2EEKfzoQXt3Nitrt/IPbT+f1fgqBdoxO3W/+JYvtEOW6EgxnWfr9GH6nmULv7Y2tPmEX3koxThVmebA==",
|
||||
"requires": {}
|
||||
},
|
||||
"source-map-js": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
"next-intl": "^3.3.1",
|
||||
"react": "^18",
|
||||
"react-dom": "^18",
|
||||
"react-slick": "^0.29.0",
|
||||
"slick-carousel": "^1.8.1",
|
||||
"styled-components": "^6.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
After Width: | Height: | Size: 61 KiB |
After Width: | Height: | Size: 86 KiB |
After Width: | Height: | Size: 180 KiB |
After Width: | Height: | Size: 312 KiB |
After Width: | Height: | Size: 90 KiB |
After Width: | Height: | Size: 297 KiB |
After Width: | Height: | Size: 149 KiB |
After Width: | Height: | Size: 384 KiB |
After Width: | Height: | Size: 112 KiB |
After Width: | Height: | Size: 100 KiB |
After Width: | Height: | Size: 55 KiB |
After Width: | Height: | Size: 74 KiB |
After Width: | Height: | Size: 2.1 MiB |
|
@ -0,0 +1,3 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M21.1404 17.5312C20.396 16.7812 18.5932 15.6867 17.7185 15.2456C16.5795 14.6718 16.4857 14.6249 15.5904 15.2901C14.9932 15.734 14.5962 16.1306 13.8973 15.9815C13.1984 15.8324 11.6796 14.992 10.3498 13.6663C9.01994 12.3407 8.13072 10.7779 7.98119 10.0813C7.83166 9.38478 8.23478 8.99244 8.67447 8.39385C9.29415 7.5501 9.24728 7.40947 8.71759 6.27041C8.30462 5.38447 7.17822 3.59853 6.42541 2.85791C5.62009 2.06244 5.62009 2.20306 5.10119 2.41869C4.67874 2.59643 4.27345 2.81249 3.89041 3.06416C3.14041 3.56244 2.72416 3.97635 2.43306 4.59838C2.14197 5.22041 2.01119 6.67869 3.51447 9.40963C5.01775 12.1406 6.07244 13.537 8.2554 15.7138C10.4384 17.8907 12.117 19.0612 14.5709 20.4374C17.6065 22.1376 18.7709 21.8062 19.3948 21.5156C20.0187 21.2249 20.4345 20.8124 20.9337 20.0624C21.186 19.68 21.4025 19.2752 21.5806 18.8531C21.7967 18.336 21.9373 18.336 21.1404 17.5312Z" stroke="#fff" stroke-width="2" stroke-miterlimit="10"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 137 KiB |
After Width: | Height: | Size: 196 KiB |
After Width: | Height: | Size: 58 KiB |
After Width: | Height: | Size: 113 KiB |
After Width: | Height: | Size: 87 KiB |
After Width: | Height: | Size: 109 KiB |
After Width: | Height: | Size: 137 KiB |
After Width: | Height: | Size: 163 KiB |
After Width: | Height: | Size: 106 KiB |
After Width: | Height: | Size: 95 KiB |
After Width: | Height: | Size: 72 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 9.8 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 9.8 KiB |
After Width: | Height: | Size: 9.8 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 122 KiB |
After Width: | Height: | Size: 116 KiB |
After Width: | Height: | Size: 1.1 KiB |
|
@ -0,0 +1,12 @@
|
|||
<svg width="170" height="170" viewBox="0 0 170 170" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g filter="url(#filter0_f_1643_242)">
|
||||
<path d="M138 85C138 114.271 114.271 138 85 138C55.7289 138 32 114.271 32 85C32 55.7289 55.7289 32 85 32C114.271 32 138 55.7289 138 85Z" fill="white"/>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_f_1643_242" x="0" y="0" width="170" height="170" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="16" result="effect1_foregroundBlur_1643_242"/>
|
||||
</filter>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 755 B |
|
@ -0,0 +1,17 @@
|
|||
import { apiClient } from '../lib/apiClient';
|
||||
import { SearchData } from '../types/tags';
|
||||
|
||||
export const getTagList = async (locale: string) => {
|
||||
const response = await apiClient.post(
|
||||
'/home/searchdata',
|
||||
{},
|
||||
{
|
||||
headers: {
|
||||
'X-User-Language': locale,
|
||||
Authorization: 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImN0eSI6IkpXVCJ9.eyJuYW1laWQiOiIxNzIiLCJuYmYiOjE3MDM2ODMyMDgsImV4cCI6MTczNTIxOTIwOCwiaWF0IjoxNzAzNjgzMjA4fQ.KgnYfKO7oVFLlDuKhfyNN6RAaXKdeSzJd7F4r6_15AA'
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return response.data as SearchData || null;
|
||||
};
|
|
@ -1,40 +1,30 @@
|
|||
import React from 'react';
|
||||
import { CustomPagination } from '../../../../components/view';
|
||||
import { ExpertsFilter } from '../../../../components/Experts/Filter';
|
||||
import { ExpertsAdditionalFilter } from '../../../../components/Experts/AdditionalFilter';
|
||||
import { ExpertsList } from '../../../../components/Experts/ExpertsList';
|
||||
import { getTranslations } from 'next-intl/server';
|
||||
import { getFilter } from '../../../../utils/filter';
|
||||
import { getExpertsList } from '../../../../actions/experts';
|
||||
import { getTagList } from '../../../../actions/tags';
|
||||
import { Experts } from '../../../../components/Experts/Experts';
|
||||
|
||||
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);
|
||||
export default async function ExpertsPage({ params, searchParams }: { params: { locale: string }, searchParams: { [key: string]: string | string[] | undefined } }) {
|
||||
const searchData = await getTagList(params.locale);
|
||||
const filter = getFilter(searchData, searchParams);
|
||||
console.log('filter main page', filter);
|
||||
const experts = await getExpertsList(filter, params.locale);
|
||||
const t = await getTranslations('Experts');
|
||||
|
||||
return (
|
||||
<div className="main-find">
|
||||
<div className="b-inner">
|
||||
<div className="main-find__top">
|
||||
<h2 className="title-h2">Find an expert</h2>
|
||||
<h2 className="title-h2">{t('title')}</h2>
|
||||
<div className="open-filter">
|
||||
<img src="/images/options-outline.svg" className="" alt=""/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-xl-3 col-lg-4 d-none d-lg-block">
|
||||
<ExpertsFilter locale={params.locale} />
|
||||
</div>
|
||||
<div className="col-xl-9 col-lg-8 ">
|
||||
<ExpertsAdditionalFilter />
|
||||
<ExpertsList data={data} locale={params.locale} />
|
||||
<CustomPagination total={20} />
|
||||
</div>
|
||||
</div>
|
||||
<Experts
|
||||
experts={experts}
|
||||
searchData={searchData}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import React from 'react';
|
||||
import type { Metadata } from 'next';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { GeneralTopSection } from '../../../components/Page';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Bbuddy - Main',
|
||||
|
@ -7,41 +9,13 @@ export const metadata: Metadata = {
|
|||
};
|
||||
|
||||
export default function Home() {
|
||||
const t = useTranslations('Main');
|
||||
|
||||
return (
|
||||
<div className="main-top">
|
||||
<div className="b-inner">
|
||||
<h1 className="title-h1">
|
||||
Mentorship, Career
|
||||
Development & Coaching.
|
||||
</h1>
|
||||
<div className="main-top__wrap-text">
|
||||
<p className="main-top__text">The ins-and-outs of building a career in tech, gaining experience </p>
|
||||
<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="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="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
|
||||
</a>
|
||||
</div>
|
||||
<div className="main-top__img">
|
||||
<img className="" src="/images/main-top.png" alt=""/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<GeneralTopSection
|
||||
title={t('header')}
|
||||
description={t('header-desc')}
|
||||
mainImage="main-top.png"
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
import { redirect } from 'next/navigation';
|
||||
|
||||
export default function AccountMainPage({ params }: { params: { userId: string } }) {
|
||||
redirect(`/${params.userId}/sessions`);
|
||||
};
|
|
@ -0,0 +1,12 @@
|
|||
import { redirect, notFound } from 'next/navigation';
|
||||
// import { checkAuthToken } from '../../../utils/storage/auth';
|
||||
|
||||
export default function AccountMainPage() {
|
||||
// if (checkAuthToken()) {
|
||||
// redirect('/sessions');
|
||||
// } else {
|
||||
// notFound();
|
||||
// }
|
||||
|
||||
redirect('/sessions');
|
||||
};
|
|
@ -0,0 +1,197 @@
|
|||
import React from 'react';
|
||||
import type { Metadata } from 'next';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { GeneralTopSection } from '../../../components/Page';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Bbuddy - Take the lead with BB',
|
||||
description: 'Bbuddy desc Take the lead with BB'
|
||||
};
|
||||
|
||||
export default function BbClientPage() {
|
||||
const t = useTranslations('BbClient');
|
||||
|
||||
return (
|
||||
<>
|
||||
<GeneralTopSection
|
||||
title={t('header')}
|
||||
mainImage="banner-phone.png"
|
||||
/>
|
||||
<div className="main-articles bb-client">
|
||||
<div className="b-inner">
|
||||
<h2 className="title-h2">How do you want to advance today?</h2>
|
||||
<div className="tag-list">
|
||||
<div className="tag-item">Work - Life Balance</div>
|
||||
<div className="tag-item">Personal growth</div>
|
||||
<div className="tag-item">Career planning</div>
|
||||
<div className="tag-item">Executive coaching</div>
|
||||
<div className="tag-item">Financial thinking</div>
|
||||
<div className="tag-item">Business development</div>
|
||||
<div className="tag-item">Startup</div>
|
||||
<div className="tag-item">Strategic session</div>
|
||||
<div className="tag-item">Relationships</div>
|
||||
<div className="tag-item">Healthy lifestyle</div>
|
||||
<div className="tag-item">Relocation</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<section className="b2">
|
||||
<div className="b-inner">
|
||||
<h2 className="title-h2">Start the path to big goals with us</h2>
|
||||
<div className="row">
|
||||
<div className="col-12 col-md-5 col-lg-6">
|
||||
<img src="/images/b-2-bg.png" alt="" className="b2-img" />
|
||||
</div>
|
||||
<div className="col-12 col-md-7 col-lg-6">
|
||||
<div className="advice-list">
|
||||
<div className="advice-item">Take advantage of coaching sessions to help you grow
|
||||
confidently by enhancing your skills and personal qualities.
|
||||
</div>
|
||||
<div className="advice-item">Allow our professionals to use their expertise to assist
|
||||
you in making a difference.
|
||||
</div>
|
||||
<div className="advice-item">Develop the required skills and steer clear of common
|
||||
pitfalls by working with a mentor.
|
||||
</div>
|
||||
<div className="advice-item">Learn new things to equip yourself with cutting-edge
|
||||
resources for advancement.
|
||||
</div>
|
||||
<div className="advice-item">Communicate with like-minded people to get even more out of
|
||||
B BUDDY.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section className="b3">
|
||||
<div className="b-inner">
|
||||
<h2 className="title-h2">B Buddy: Reliable and convenient</h2>
|
||||
<div className="row">
|
||||
<div className="col-12 col-sm-6 col col-lg-3">
|
||||
<div className="b3-item">
|
||||
<img src="/images/b-3-1.svg" className="b3-img"/>
|
||||
<div className="b3-title">from 300 hours</div>
|
||||
<div className="b3-text">experience of each coach</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-12 col-sm-6 col col-lg-3">
|
||||
<div className="b3-item">
|
||||
<img src="/images/b-3-2.svg" className="b3-img"/>
|
||||
<div className="b3-title">25 countries
|
||||
</div>
|
||||
<div className="b3-text">location of participants
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-12 col-sm-6 col col-lg-3">
|
||||
<div className="b3-item">
|
||||
<img src="/images/b-3-3.svg" className="b3-img"/>
|
||||
<div className="b3-title">15 criteria</div>
|
||||
<div className="b3-text">use B BUDDY to find the best mentor
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-12 col-sm-6 col col-lg-3">
|
||||
<div className="b3-item">
|
||||
<img src="/images/b-3-4.svg" className="b3-img"/>
|
||||
<div className="b3-title">5 minutes</div>
|
||||
<div className="b3-text">from registering to speaking with an expert
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section className="b4">
|
||||
<div className="b-inner">
|
||||
<div className="row">
|
||||
<div className="col-md-7 col-lg-6">
|
||||
<div className="b4-list">
|
||||
<div className="b4-item">
|
||||
<div className="b4-title">All in one</div>
|
||||
<div className="b4-descr">
|
||||
Whether it's self-evaluation, public speaking, or
|
||||
financial planning, B BUDDY can provide the support you need in one single
|
||||
application. Now your smartphone has even more room for stunning photos.
|
||||
</div>
|
||||
</div>
|
||||
<div className="b4-item">
|
||||
<div className="b4-title">The solution is right in your pocket</div>
|
||||
<div className="b4-descr">
|
||||
Get expert help as soon as you need it. A smartphone is
|
||||
always within reach. Your competitive advantage is speed.
|
||||
</div>
|
||||
</div>
|
||||
<div className="b4-item">
|
||||
<div className="b4-title">Focus on your top priorities</div>
|
||||
<div className="b4-descr">
|
||||
Make a call, schedule a meeting, set a reminder, and save
|
||||
a link to a video conference. This can all be done with a single click using the
|
||||
B BUDDY app. Let us take care of the rest while you focus on the things that
|
||||
count.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-md-5 col-lg-6 position-relative">
|
||||
<img src="/images/girl.png" alt="" className="b4-img" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section className="b5 waves-top">
|
||||
<div className="b-inner">
|
||||
<h2 className="title-h2">B BUDDY will</h2>
|
||||
<div className="row">
|
||||
<div className="col-12 col-sm-6 col-lg-3">
|
||||
<div className="b5-item">
|
||||
<img src="/images/b-5-1.svg" alt="" className="b5-img" />
|
||||
<div className="b5-text">Choose a professional who is a perfect fit for you</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-12 col-sm-6 col-lg-3">
|
||||
<div className="b5-item">
|
||||
<img src="/images/b-5-2.svg" alt="" className="b5-img" />
|
||||
<div className="b5-text">Set up meetings</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-12 col-sm-6 col-lg-3">
|
||||
<div className="b5-item">
|
||||
<img src="/images/b-5-3.svg" alt="" className="b5-img" />
|
||||
<div className="b5-text">Notify you in advance of the scheduled session</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-12 col-sm-6 col-lg-3">
|
||||
<div className="b5-item">
|
||||
<img src="/images/b-5-4.svg" alt="" className="b5-img" />
|
||||
<div className="b5-text">Invite you to a video call at the appropriate time</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<h3>Isn’t that amazing?</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section className="b6">
|
||||
<div className="b-inner">
|
||||
<div className="b6-banner">
|
||||
<div className="b6-content">
|
||||
<div className="b6-title">Being formed by business owners and educators, B BUDDY is
|
||||
completely aware of what is required and how to deliver it to you.
|
||||
</div>
|
||||
<div className="b6-descr">We work hard to support people in becoming more successful! We
|
||||
therefore strive daily to make B BUDDY the top coaching, mentoring, and consulting
|
||||
application.
|
||||
</div>
|
||||
</div>
|
||||
<img src="/images/b-6-img.png" alt="" className="b6-img" />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,129 @@
|
|||
import React from 'react';
|
||||
import type { Metadata } from 'next';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { GeneralTopSection } from '../../../components/Page';
|
||||
import { ScreenCarousel } from '../../../components/Page/ScreenCarousel/index';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Bbuddy - Become a BB expert',
|
||||
description: 'Bbuddy desc Become a BB expert'
|
||||
};
|
||||
|
||||
export default function BbExpertPage() {
|
||||
const t = useTranslations('BbExpert');
|
||||
|
||||
return (
|
||||
<>
|
||||
<GeneralTopSection
|
||||
title={t('header')}
|
||||
description={t('header-desc')}
|
||||
mainImage="banner-people.png"
|
||||
/>
|
||||
<section className="b-slider waves-top">
|
||||
<ScreenCarousel />
|
||||
</section>
|
||||
<section className="b2" style={{ padding: '40px 0' }}>
|
||||
<div className="b-inner">
|
||||
<h2 className="title-h2">Everything you need in one application</h2>
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<div className="advice-list">
|
||||
<div className="advice-item advice-item--with-img">
|
||||
<img src="/images/search.svg" alt="" className="advice-img" />
|
||||
<div className="advice-content">
|
||||
<div className="advice-title">
|
||||
Customer search
|
||||
</div>
|
||||
<div className="advice-text">
|
||||
The application algorithm will match your profile data to the customer’s
|
||||
request and recommend the best option. BB customers will come directly
|
||||
to you!
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="advice-item advice-item--with-img">
|
||||
<img src="/images/note.svg" alt="" className="advice-img" />
|
||||
<div className="advice-content">
|
||||
<div className="advice-title">
|
||||
Automation of appointments
|
||||
</div>
|
||||
<div className="advice-text">
|
||||
Create your work schedule only once. Customers will make their own
|
||||
appointments thereafter selecting a time slot on your calendar.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="advice-item advice-item--with-img">
|
||||
<img src="/images/videocall.svg" alt="" className="advice-img" />
|
||||
<div className="advice-content">
|
||||
<div className="advice-title">
|
||||
Video calls
|
||||
</div>
|
||||
<div className="advice-text">
|
||||
Call up directly in B Buddy at the touch of a button. No more flicking
|
||||
through apps in search of a link. A gentle reminder required? We will
|
||||
send one.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="advice-item advice-item--with-img">
|
||||
<img src="/images/guard.svg" alt="" className="advice-img" />
|
||||
<div className="advice-content">
|
||||
<div className="advice-title">
|
||||
Legal security
|
||||
</div>
|
||||
<div className="advice-text">All required documents, including the contract
|
||||
and consent to the processing of personal data, have been verified and
|
||||
are available in the app.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="advice-item advice-item--with-img">
|
||||
<img src="/images/feedback.svg" alt="" className="advice-img" />
|
||||
<div className="advice-content">
|
||||
<div className="advice-title">
|
||||
Feedback
|
||||
</div>
|
||||
<div className="advice-text">Gather feedback from all the customers in one
|
||||
place. B Buddy will remind the customer to leave feedback after the
|
||||
meeting is over.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section className="b3">
|
||||
<div className="b-inner">
|
||||
<h2 className="title-h2">B Buddy expert has:</h2>
|
||||
<div className="row">
|
||||
<div className="col-12 col-md-4">
|
||||
<div className="b3-item">
|
||||
<img src="/images/calendar.svg" className="b3-img"/>
|
||||
<div className="b3-title">From 300 hours</div>
|
||||
<div className="b3-text">Coaching practice</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-12 col-md-4">
|
||||
<div className="b3-item">
|
||||
<img src="/images/man.svg" className="b3-img"/>
|
||||
<div className="b3-title">From 5 years</div>
|
||||
<div className="b3-text">Professional experience</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-12 col-md-4">
|
||||
<div className="b3-item">
|
||||
<img src="/images/target.svg" className="b3-img"/>
|
||||
<div className="b3-title">Expertise</div>
|
||||
<div className="b3-text">Confirmed by successfully implemented projects
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</>
|
||||
);
|
||||
};
|
|
@ -1,48 +1,37 @@
|
|||
import React from 'react';
|
||||
import type { Metadata } from 'next';
|
||||
import { getTranslations } from 'next-intl/server';
|
||||
import { getFilter } from '../../../utils/filter';
|
||||
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';
|
||||
import { getTagList } from '../../../actions/tags';
|
||||
import { Experts } from '../../../components/Experts/Experts';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Bbuddy - Experts',
|
||||
description: 'Bbuddy desc experts'
|
||||
};
|
||||
|
||||
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);
|
||||
export default async function ExpertsPage({ params, searchParams }: { params: { locale: string }, searchParams: { [key: string]: string | string[] | undefined } }) {
|
||||
const searchData = await getTagList(params.locale);
|
||||
const filter = getFilter(searchData, searchParams);
|
||||
console.log('filter experts page', filter);
|
||||
const experts = await getExpertsList(filter, params.locale);
|
||||
const t = await getTranslations('Experts');
|
||||
|
||||
return (
|
||||
<div className="page-search">
|
||||
<div className="main-find">
|
||||
<div className="b-inner">
|
||||
<div className="main-find__top">
|
||||
<h2 className="title-h2">Find a expert</h2>
|
||||
<h2 className="title-h2">{t('title')}</h2>
|
||||
<div className="open-filter">
|
||||
<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 locale={params.locale} />
|
||||
</div>
|
||||
<div className="col-xl-9 col-lg-8 ">
|
||||
<ExpertsAdditionalFilter />
|
||||
<ExpertsList data={data} locale={params.locale} />
|
||||
<CustomPagination total={20} />
|
||||
</div>
|
||||
</div>
|
||||
<Experts
|
||||
experts={experts}
|
||||
searchData={searchData}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -8,8 +8,82 @@ export const metadata: Metadata = {
|
|||
|
||||
export default function Faq() {
|
||||
return (
|
||||
<div>
|
||||
Страница faq
|
||||
<>
|
||||
<section className="banner banner-faq">
|
||||
<div className="b-inner">
|
||||
<div className="row">
|
||||
<div className="col-12 col-md-7 col-xl-6 text-center">
|
||||
<h1 className="mb-4">Frequently asked questions</h1>
|
||||
<div className="banner-note mb-4">
|
||||
Do you have any questions? Call!
|
||||
</div>
|
||||
<div className="store-buttons justify-content-center">
|
||||
<a href="tel:+35799752176" className="store-button phone">+3 579 97 52 176</a>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-12 col-md-5 col-xl-6 position-relative">
|
||||
<img src="/images/faq-img.png" alt="" className="banner-img" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section className="b2 mb-5">
|
||||
<div className="b-inner">
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<div className="advice-list mb-5">
|
||||
<div className="advice-item advice-item--with-img">
|
||||
<img src="/images/cash.svg" alt="" className="advice-img" />
|
||||
<div className="advice-content">
|
||||
<div className="advice-title">
|
||||
How much will I earn for the consultation?
|
||||
</div>
|
||||
<div className="advice-text">
|
||||
It is entirely up to you because you set the price for the services.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="advice-item advice-item--with-img">
|
||||
<img src="/images/comission.svg" alt="" className="advice-img" />
|
||||
<div className="advice-content">
|
||||
<div className="advice-title">
|
||||
What will BBuddy’s commission be?
|
||||
</div>
|
||||
<div className="advice-text">
|
||||
B Buddy will receive 15% commission of the consultation cost.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="advice-item advice-item--with-img">
|
||||
<img src="/images/new-client.svg" alt="" className="advice-img" />
|
||||
<div className="advice-content">
|
||||
<div className="advice-title">
|
||||
Can I bring my customer?
|
||||
</div>
|
||||
<div className="advice-text">
|
||||
You will be able to invite existing customers to the application via a
|
||||
unique link. B Buddy will not charge a fee for transferring your
|
||||
existing customers.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="advice-item advice-item--with-img">
|
||||
<img src="/images/new-expert.svg" alt="" className="advice-img" />
|
||||
<div className="advice-content">
|
||||
<div className="advice-title">
|
||||
What about if I introduce a new expert to B Buddy?
|
||||
</div>
|
||||
<div className="advice-text">
|
||||
Within two months of the date of his platform registration, you will
|
||||
receive 5% of each of his consultations.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
import React from 'react';
|
||||
import type { Metadata } from 'next';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Bbuddy - Privacy Policy',
|
||||
description: 'Bbuddy desc search'
|
||||
};
|
||||
|
||||
export default function PrivacyPolicy() {
|
||||
return (
|
||||
<div>
|
||||
Privacy policy
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -1,51 +1,85 @@
|
|||
'use client';
|
||||
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import { Select } from 'antd';
|
||||
import {Button, Select} from 'antd';
|
||||
import { useSearchParams } from 'next/navigation';
|
||||
import { useRouter } from '../../navigation';
|
||||
import { AdditionalFilter } from '../../types/experts';
|
||||
import { INITIAL_ADD_FILTER } from '../../constants/experts';
|
||||
import { LOCALES } from '../../constants/locale';
|
||||
import { getObjectByFilter, getObjectByAdditionalFilter } from '../../utils/filter';
|
||||
import { CustomInput } from '../view';
|
||||
|
||||
export const ExpertsAdditionalFilter = () => {
|
||||
const [filter, setFilter] = useState<AdditionalFilter>(INITIAL_ADD_FILTER);
|
||||
type ExpertAdditionalFilterProps = {
|
||||
searchPlaceholder: string;
|
||||
sortLabel: string;
|
||||
langLabel: string;
|
||||
buttonFind: string;
|
||||
basePath?: string;
|
||||
};
|
||||
|
||||
export const ExpertsAdditionalFilter = ({
|
||||
searchPlaceholder,
|
||||
sortLabel,
|
||||
langLabel,
|
||||
buttonFind,
|
||||
basePath = '/',
|
||||
}): ExpertAdditionalFilterProps => {
|
||||
const searchParams = useSearchParams();
|
||||
const router = useRouter();
|
||||
const [filter, setFilter] = useState<AdditionalFilter | undefined>(getObjectByAdditionalFilter(searchParams));
|
||||
|
||||
const onChangeFilter = useCallback((key: string, value: any) => {
|
||||
setFilter({
|
||||
...filter,
|
||||
[key]: value
|
||||
})
|
||||
// setFilter({
|
||||
// ...filter,
|
||||
// [key]: value
|
||||
// })
|
||||
}, [filter]);
|
||||
|
||||
const goToFilterPage = useCallback(() => {
|
||||
router.push({
|
||||
pathname: basePath,
|
||||
query: {
|
||||
...getObjectByFilter(searchParams),
|
||||
...filter
|
||||
}
|
||||
})
|
||||
}, [filter, searchParams]);
|
||||
|
||||
return (
|
||||
<div className="main-find__search">
|
||||
<div className="main-find__search__input">
|
||||
<CustomInput
|
||||
placeholder="Search for an Expert"
|
||||
placeholder={searchPlaceholder}
|
||||
defaultValue={filter?.text}
|
||||
onChange={(e: any) => onChangeFilter('text', e?.target?.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="main-find__search__sort">
|
||||
<Select
|
||||
defaultValue={INITIAL_ADD_FILTER.sort}
|
||||
defaultValue={filter?.sort}
|
||||
onChange={(val) => onChangeFilter('sort', val)}
|
||||
options={[
|
||||
{ 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' }
|
||||
{ value: 'byTop', label: 'By top views' },
|
||||
{ value: 'byPriceAsc', label: 'By price ascending' },
|
||||
{ value: 'byPriceDesc', label: 'By price descending' },
|
||||
{ value: 'byRating', label: 'By rating' }
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
<div className="main-find__search__language">
|
||||
<Select
|
||||
mode="multiple"
|
||||
defaultValue={INITIAL_ADD_FILTER.language}
|
||||
defaultValue={filter?.language}
|
||||
onChange={(val) => onChangeFilter('language', val)}
|
||||
options={Object.entries(LOCALES).map(([ value, label ]) => ({ value, label }))}
|
||||
/>
|
||||
</div>
|
||||
<button className="btn-apply">Find</button>
|
||||
<Button
|
||||
className="btn-apply"
|
||||
onClick={goToFilterPage}
|
||||
>
|
||||
{buttonFind}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
import React from 'react';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { SearchData } from '../../types/tags';
|
||||
import { ExpertsData } from '../../types/experts';
|
||||
import { ExpertsFilter } from './Filter';
|
||||
import { ExpertsAdditionalFilter } from './AdditionalFilter';
|
||||
import { ExpertsList } from './ExpertsList';
|
||||
import { CustomPagination } from '../view/CustomPagination';
|
||||
|
||||
type ExpertsProps = {
|
||||
searchData?: SearchData;
|
||||
experts?: ExpertsData;
|
||||
};
|
||||
|
||||
export const Experts = ({ searchData, experts }: ExpertsProps) => {
|
||||
const t = useTranslations('Experts');
|
||||
|
||||
return (
|
||||
<div className="row">
|
||||
<div className="col-xl-3 col-lg-4 d-none d-lg-block">
|
||||
<ExpertsFilter
|
||||
searchData={searchData}
|
||||
basePath="/experts"
|
||||
priceTitle={t('filter.price', { from: searchData.sessionCostMin, to: searchData.sessionCostMax })}
|
||||
durationTitle={t('filter.duration', { from: searchData.sessionDurationMin, to: searchData.sessionDurationMax })}
|
||||
buttonApply={t('filter.apply')}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-xl-9 col-lg-8 ">
|
||||
<ExpertsAdditionalFilter
|
||||
searchPlaceholder={t('filter.search')}
|
||||
sortLabel={t('filter.sort')}
|
||||
langLabel={t('filter.language')}
|
||||
buttonFind={t('filter.find')}
|
||||
basePath="/experts"
|
||||
/>
|
||||
<ExpertsList
|
||||
data={experts}
|
||||
priceTitle={t('list.price')}
|
||||
durationTitle={t('list.duration')}
|
||||
detailButton={t('list.details')}
|
||||
/>
|
||||
<CustomPagination total={20} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
};
|
|
@ -5,11 +5,22 @@ 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;
|
||||
type ExpertListProps = {
|
||||
data: ExpertsData;
|
||||
priceTitle: string;
|
||||
durationTitle: string;
|
||||
detailButton: string;
|
||||
};
|
||||
|
||||
export const ExpertsList = ({
|
||||
data,
|
||||
priceTitle,
|
||||
durationTitle,
|
||||
detailButton
|
||||
}: ExpertListProps) => {
|
||||
const getTitle = (str: string, value?: any): string => (value ? str.replace('0', value) : str);
|
||||
|
||||
return (
|
||||
<List
|
||||
|
@ -32,7 +43,7 @@ export const ExpertsList = ({ data, locale }: { data: ExpertsData, locale: strin
|
|||
<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>
|
||||
{getTitle(priceTitle, item?.sessionCost)} <span>/ {getTitle(durationTitle, item?.sessionDuration)}</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
@ -55,7 +66,7 @@ export const ExpertsList = ({ data, locale }: { data: ExpertsData, locale: strin
|
|||
<div className="card-profile__desc">{item?.description}</div>
|
||||
<div className="card-profile__footer">
|
||||
<Link href={`/experts/${item?.id}` as any}>
|
||||
Details
|
||||
{detailButton}
|
||||
<RightOutlined style={{ fontSize: '10px', padding: '0 7px' }}/>
|
||||
</Link>
|
||||
</div>
|
||||
|
|
|
@ -1,65 +1,97 @@
|
|||
'use client';
|
||||
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import { List } from 'antd';
|
||||
import { FilterType, INITIAL_FILTER } from '../../constants/experts';
|
||||
import { Button, List } from 'antd';
|
||||
import { useSearchParams } from 'next/navigation';
|
||||
import { Filter } from '../../types/experts';
|
||||
import { SearchData, Tag } from '../../types/tags';
|
||||
import { useRouter } from '../../navigation';
|
||||
import { getObjectByFilter, getObjectByAdditionalFilter } from '../../utils/filter';
|
||||
import { CustomSwitch, CustomSlider } from '../view';
|
||||
import {Locale} from "../../types/locale";
|
||||
|
||||
const dataCoaching = [
|
||||
{
|
||||
key: FilterType.WorkLifeBalance,
|
||||
title: 'Work-life Balance'
|
||||
},
|
||||
{
|
||||
key: FilterType.StrategicSession,
|
||||
title: 'Strategic Session'
|
||||
},
|
||||
{
|
||||
key: FilterType.PersonalGrowth,
|
||||
title: 'Personal Growth'
|
||||
},
|
||||
{
|
||||
key: FilterType.PersonalGrowth,
|
||||
title: 'Career Planning'
|
||||
},
|
||||
{
|
||||
key: FilterType.ExecutiveCoaching,
|
||||
title: 'Executive Coaching'
|
||||
type ExpertsFilterProps = {
|
||||
searchData: SearchData;
|
||||
basePath?: string;
|
||||
priceTitle: string;
|
||||
durationTitle: string;
|
||||
buttonApply: string;
|
||||
};
|
||||
|
||||
export const ExpertsFilter = ({
|
||||
searchData,
|
||||
basePath = '/',
|
||||
priceTitle,
|
||||
durationTitle,
|
||||
buttonApply
|
||||
}: ExpertsFilterProps) => {
|
||||
const searchParams = useSearchParams();
|
||||
const router = useRouter();
|
||||
const [filter, setFilter] = useState<Filter | undefined>(getObjectByFilter(searchParams));
|
||||
|
||||
const onChangeTags = useCallback((id: number, checked: boolean) => {
|
||||
let themesTagIds = filter?.themesTagIds || [];
|
||||
|
||||
if (checked && !themesTagIds?.includes(id)) {
|
||||
themesTagIds.push(id);
|
||||
}
|
||||
];
|
||||
|
||||
const dataMentoring = [
|
||||
{
|
||||
key: FilterType.CareerDevelopment,
|
||||
title: 'Career Development'
|
||||
},
|
||||
{
|
||||
key: FilterType.Networking,
|
||||
title: 'Networking'
|
||||
if (!checked && themesTagIds?.includes(id)) {
|
||||
themesTagIds = themesTagIds.filter((tId) => tId != id);
|
||||
}
|
||||
];
|
||||
|
||||
const dataConsultation = [
|
||||
{
|
||||
key: FilterType.BusinessModelReview,
|
||||
title: 'Business Model Review'
|
||||
}
|
||||
];
|
||||
|
||||
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({
|
||||
...filter,
|
||||
[key]: value
|
||||
})
|
||||
}, [filter]);
|
||||
themesTagIds
|
||||
});
|
||||
}, [filter, searchParams, searchData]);
|
||||
|
||||
const getList = useCallback((data: any[]) => (
|
||||
const onChangePrice = useCallback(([min, max]: number[]) => {
|
||||
const newFilter: Filter = {
|
||||
...filter,
|
||||
priceFrom: min,
|
||||
priceTo: max
|
||||
};
|
||||
|
||||
if (newFilter.priceFrom === searchData?.sessionCostMin) {
|
||||
delete newFilter.priceFrom;
|
||||
}
|
||||
|
||||
if (newFilter.priceTo === searchData?.sessionCostMax) {
|
||||
delete newFilter.priceTo;
|
||||
}
|
||||
|
||||
setFilter(newFilter);
|
||||
}, [filter, searchParams, searchData]);
|
||||
|
||||
const onChangeDuration = useCallback(([min, max]: number[]) => {
|
||||
const newFilter: Filter = {
|
||||
...filter,
|
||||
durationFrom: min,
|
||||
durationTo: max
|
||||
};
|
||||
|
||||
if (newFilter.durationFrom === searchData?.sessionDurationMin) {
|
||||
delete newFilter.durationFrom;
|
||||
}
|
||||
|
||||
if (newFilter.durationTo === searchData?.sessionDurationMax) {
|
||||
delete newFilter.durationTo;
|
||||
}
|
||||
|
||||
setFilter(newFilter);
|
||||
}, [filter, searchParams, searchData]);
|
||||
|
||||
const goToFilterPage = useCallback(() => {
|
||||
router.push({
|
||||
pathname: basePath,
|
||||
query: {
|
||||
...filter,
|
||||
...getObjectByAdditionalFilter(searchParams)
|
||||
}
|
||||
})
|
||||
}, [filter, searchParams, searchData]);
|
||||
|
||||
const getList = useCallback((data: Tag[]) => (
|
||||
<div className="b-filter__inner">
|
||||
<List
|
||||
itemLayout="vertical"
|
||||
|
@ -67,52 +99,57 @@ export const ExpertsFilter = ({ locale }: { locale: string }) => {
|
|||
dataSource={data}
|
||||
split={false}
|
||||
style={{ width: '100%' }}
|
||||
renderItem={({ key, title }) => (
|
||||
<List.Item key={key} style={{ padding: 0 }}>
|
||||
renderItem={({ id, name }) => (
|
||||
<List.Item key={id} style={{ padding: 0 }}>
|
||||
<div className="b-filter__item">
|
||||
<div className="b-filter__title">{title}</div>
|
||||
<div className="b-filter__title">{name}</div>
|
||||
<CustomSwitch
|
||||
defaultChecked={filter[key]}
|
||||
onChange={(checked: boolean) => onChangeFilter(key, checked)}
|
||||
defaultChecked={filter?.themesTagIds?.includes(id) || false}
|
||||
onChange={(checked: boolean) => onChangeTags(id, checked)}
|
||||
/>
|
||||
</div>
|
||||
</List.Item>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
), [filter]);
|
||||
), [filter, searchParams, searchData]);
|
||||
|
||||
return (
|
||||
<div className="b-filter">
|
||||
<h3 className="title-h3">Coaching</h3>
|
||||
{getList(dataCoaching)}
|
||||
<h3 className="title-h3">Mentoring</h3>
|
||||
{getList(dataMentoring)}
|
||||
<h3 className="title-h3">Business-consultation</h3>
|
||||
{getList(dataConsultation)}
|
||||
<h3 className="title-h3">{`Price from 45${isRus ? '₽' : '€'} to 170${isRus ? '₽' : '€'}`}</h3>
|
||||
{searchData.themesGroups?.length && searchData.themesGroups.map(({ id, name, tags }) => (
|
||||
<div key={id}>
|
||||
<h3 className="title-h3">{name}</h3>
|
||||
{getList(tags)}
|
||||
</div>
|
||||
))}
|
||||
<h3 className="title-h3">{priceTitle}</h3>
|
||||
<div className="b-filter__slider">
|
||||
<CustomSlider
|
||||
range
|
||||
step={1}
|
||||
defaultValue={INITIAL_FILTER[FilterType.Price]}
|
||||
min={45}
|
||||
max={170}
|
||||
onChange={(val: any) => onChangeFilter(FilterType.Price, val)}
|
||||
defaultValue={[filter?.priceFrom || searchData.sessionCostMin, filter?.priceTo || searchData.sessionCostMax]}
|
||||
min={searchData.sessionCostMin}
|
||||
max={searchData.sessionCostMax}
|
||||
onChange={onChangePrice}
|
||||
/>
|
||||
</div>
|
||||
<h3 className="title-h3">{`Duration from 45${isRus ? 'мин' : 'min'} to 120${isRus ? 'мин' : 'min'}`}</h3>
|
||||
<h3 className="title-h3">{durationTitle}</h3>
|
||||
<div className="b-filter__slider">
|
||||
<CustomSlider
|
||||
range
|
||||
step={1}
|
||||
defaultValue={INITIAL_FILTER[FilterType.Duration]}
|
||||
min={45}
|
||||
max={120}
|
||||
onChange={(val: any) => onChangeFilter(FilterType.Duration, val)}
|
||||
defaultValue={[filter?.durationFrom || searchData.sessionDurationMin, filter?.durationTo || searchData.sessionDurationMax]}
|
||||
min={searchData.sessionDurationMin}
|
||||
max={searchData.sessionDurationMax}
|
||||
onChange={onChangeDuration}
|
||||
/>
|
||||
</div>
|
||||
<button className="btn-apply">Apply</button>
|
||||
<Button
|
||||
className="btn-apply"
|
||||
onClick={goToFilterPage}
|
||||
>
|
||||
{buttonApply}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -8,6 +8,7 @@ import { CloseOutlined } from '@ant-design/icons';
|
|||
import { styled } from 'styled-components';
|
||||
import { CustomInput } from '../view';
|
||||
import { getAuth } from '../../actions/auth';
|
||||
import {setAuthToken} from "../../utils/storage/auth";
|
||||
|
||||
type AuthModalProps = {
|
||||
open: boolean;
|
||||
|
@ -87,7 +88,10 @@ export const AuthModal: FC<AuthModalProps> = ({
|
|||
setIsLoading(true);
|
||||
getAuth(login, password, paths[1])
|
||||
.then(({ data }) => {
|
||||
console.log('jwt', data.jwtToken)
|
||||
if (data.jwtToken) {
|
||||
setAuthToken(data.jwtToken);
|
||||
handleCancel();
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
notification.error({
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react';
|
||||
import Link from 'next/link';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { Link } from '../../../navigation';
|
||||
import { FOOTER_ROUTES } from '../../../constants/routes';
|
||||
import { Link as IntlLink } from '../../../navigation';
|
||||
|
||||
export const Footer = () => {
|
||||
const t = useTranslations('Footer');
|
||||
|
@ -35,9 +35,8 @@ export const Footer = () => {
|
|||
</div>
|
||||
<div className="b-footer__coll-2">
|
||||
<div className="b-footer__coll-2__item">
|
||||
{FOOTER_ROUTES.map((item) => (
|
||||
<Link key={item} href={`/${item}` as any} className="b-footer__link">{t(`menu.${item}`)}</Link>
|
||||
))}
|
||||
<IntlLink href={'/faq' as any} className="b-footer__link">{t('menu.faq')}</IntlLink>
|
||||
<Link href={'/docs/BBUDDY_privacy_policy_fin.docx' as any} className="b-footer__link">{t(`menu.privacy-policy`)}</Link>
|
||||
</div>
|
||||
<div className="b-footer__social">
|
||||
<a href="#" className="b-footer__link">
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
import React from 'react';
|
||||
|
||||
type GeneralTopSectionProps = {
|
||||
title: string;
|
||||
description?: string;
|
||||
mainImage: string;
|
||||
};
|
||||
|
||||
export const GeneralTopSection = ({
|
||||
title,
|
||||
description,
|
||||
mainImage
|
||||
}: GeneralTopSectionProps) => (
|
||||
<div className="main-top">
|
||||
<div className="b-inner">
|
||||
<h1 className="title-h1">{title}</h1>
|
||||
<div className="main-top__wrap-text">
|
||||
{description && <p className="main-top__text">{description}</p>}
|
||||
</div>
|
||||
<div className="main-top__wrap-btn">
|
||||
<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="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
|
||||
</a>
|
||||
</div>
|
||||
<div className="main-top__img">
|
||||
<img className="" src={`/images/${mainImage}`} alt=""/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
|
@ -4,10 +4,13 @@ import React, { FC, useState, useEffect } from 'react';
|
|||
import { Button } from 'antd';
|
||||
import { styled } from 'styled-components';
|
||||
import { AuthModal } from '../../Modals/AuthModal';
|
||||
import {checkAuthToken} from "../../../utils/storage/auth";
|
||||
import {Link} from "../../../navigation";
|
||||
|
||||
type HeaderAuthLinksProps = {
|
||||
enterTitle: string;
|
||||
registerTitle: string;
|
||||
accountTitle: string;
|
||||
separatorClass?: string;
|
||||
};
|
||||
|
||||
|
@ -24,6 +27,7 @@ const LinkButton = styled(Button)`
|
|||
export const HeaderAuthLinks: FC<HeaderAuthLinksProps> = ({
|
||||
enterTitle,
|
||||
registerTitle,
|
||||
accountTitle,
|
||||
separatorClass = 'b-header__nav__list__line'
|
||||
}) => {
|
||||
const [isOpenModal, setIsOpenModal] = useState<boolean>(false);
|
||||
|
@ -40,7 +44,13 @@ export const HeaderAuthLinks: FC<HeaderAuthLinksProps> = ({
|
|||
setIsOpenModal(true);
|
||||
};
|
||||
|
||||
return (
|
||||
return checkAuthToken()
|
||||
? (
|
||||
<li>
|
||||
<Link href={'/sessions' as any}>{accountTitle}</Link>
|
||||
</li>
|
||||
)
|
||||
: (
|
||||
<>
|
||||
<li>
|
||||
<LinkButton
|
||||
|
|
|
@ -5,14 +5,15 @@ type HeaderMenuProps = {
|
|||
children: ReactNode;
|
||||
enterTitle: string;
|
||||
registerTitle: string;
|
||||
accountTitle: string;
|
||||
};
|
||||
|
||||
export const HeaderMenu = ({ children, enterTitle, registerTitle }: HeaderMenuProps) => (
|
||||
export const HeaderMenu = ({ children, enterTitle, registerTitle, accountTitle }: HeaderMenuProps) => (
|
||||
<div className="b-header__nav">
|
||||
<nav>
|
||||
<ul className="b-header__nav__list ">
|
||||
{children}
|
||||
<HeaderAuthLinks enterTitle={enterTitle} registerTitle={registerTitle} />
|
||||
<HeaderAuthLinks enterTitle={enterTitle} registerTitle={registerTitle} accountTitle={accountTitle} />
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
|
|
@ -7,9 +7,10 @@ type HeaderMenuMobileProps = {
|
|||
children: ReactNode;
|
||||
enterTitle: string;
|
||||
registerTitle: string;
|
||||
accountTitle: string;
|
||||
};
|
||||
|
||||
export const HeaderMobileMenu: FC<HeaderMenuMobileProps> = ({ children, enterTitle, registerTitle }) => {
|
||||
export const HeaderMobileMenu: FC<HeaderMenuMobileProps> = ({ children, enterTitle, registerTitle, accountTitle }) => {
|
||||
const [showMobileMenu, setShowMobileMenu] = useState<boolean>(false);
|
||||
|
||||
return (
|
||||
|
@ -33,6 +34,7 @@ export const HeaderMobileMenu: FC<HeaderMenuMobileProps> = ({ children, enterTit
|
|||
separatorClass="menu-mobile__header__nav__line"
|
||||
enterTitle={enterTitle}
|
||||
registerTitle={registerTitle}
|
||||
accountTitle={accountTitle}
|
||||
/>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
@ -30,13 +30,13 @@ export const Header: FC<HeaderProps> = ({ locale }) => {
|
|||
alt=""
|
||||
/>
|
||||
</Link>
|
||||
<HeaderMenu enterTitle={t('enter')} registerTitle={t('registration')}>
|
||||
<HeaderMenu enterTitle={t('enter')} registerTitle={t('registration')} accountTitle={t('account')}>
|
||||
{routes}
|
||||
</HeaderMenu>
|
||||
<LanguageSwitcher locale={locale} />
|
||||
</div>
|
||||
</header>
|
||||
<HeaderMobileMenu enterTitle={t('enter')} registerTitle={t('registration')}>
|
||||
<HeaderMobileMenu enterTitle={t('enter')} registerTitle={t('registration')} accountTitle={t('account')}>
|
||||
{routes}
|
||||
</HeaderMobileMenu>
|
||||
</>
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
'use client';
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import Slider from 'react-slick';
|
||||
import 'slick-carousel/slick/slick.css';
|
||||
import 'slick-carousel/slick/slick-theme.css';
|
||||
|
||||
const ScreenList = [
|
||||
{
|
||||
id: '1',
|
||||
title: 'Plan your working hours',
|
||||
screen: '/images/slider-1.png'
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
title: 'Accept customers applications',
|
||||
screen: '/images/slider-2.png'
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
title: 'Make video calls',
|
||||
screen: '/images/slider-3.png'
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
title: 'Keep statistics',
|
||||
screen: '/images/slider-4.png'
|
||||
},
|
||||
{
|
||||
id: '5',
|
||||
title: 'Get paid',
|
||||
screen: '/images/slider-5.png'
|
||||
},
|
||||
{
|
||||
id: '6',
|
||||
title: 'Plan your working hours',
|
||||
screen: '/images/slider-1.png'
|
||||
},
|
||||
{
|
||||
id: '7',
|
||||
title: 'Accept customers applications',
|
||||
screen: '/images/slider-2.png'
|
||||
},
|
||||
{
|
||||
id: '8',
|
||||
title: 'Make video calls',
|
||||
screen: '/images/slider-3.png'
|
||||
},
|
||||
{
|
||||
id: '9',
|
||||
title: 'Keep statistics',
|
||||
screen: '/images/slider-4.png'
|
||||
},
|
||||
{
|
||||
id: '10',
|
||||
title: 'Get paid',
|
||||
screen: '/images/slider-5.png'
|
||||
}
|
||||
];
|
||||
|
||||
export const ScreenCarousel = () => {
|
||||
const [title, setTitle] = useState<string>(ScreenList[0].title);
|
||||
const settings = {
|
||||
dots: false,
|
||||
autoplay: true,
|
||||
infinite: true,
|
||||
speed: 500,
|
||||
slidesToShow: 5,
|
||||
slidesToScroll: 1,
|
||||
arrows: false,
|
||||
afterChange: (current: number) => {
|
||||
setTitle(ScreenList[current].title);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="b-inner">
|
||||
<h2 id="slider-title" className="title-h2">{title}</h2>
|
||||
<Slider {...settings} className="slider">
|
||||
{ScreenList.map(({ id, screen }) => (
|
||||
<div key={id} className="slider-item">
|
||||
<img src={screen} alt="" className="slider-img" />
|
||||
</div>
|
||||
))}
|
||||
</Slider>
|
||||
</div>
|
||||
);
|
||||
};
|
|
@ -1,2 +1,3 @@
|
|||
export * from './Header';
|
||||
export * from './Footer';
|
||||
export * from './GeneralTopSection';
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
export const BASE_URL = process.env.NEXT_PUBLIC_SERVER_BASE_URL || 'https://api.bbuddy.expert/api';
|
||||
export const AUTH_TOKEN_KEY = 'bbuddy_token';
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
import { AdditionalFilter, Filter } from '../types/experts';
|
||||
import { LOCALES } from './locale';
|
||||
|
||||
export enum FilterType {
|
||||
'WorkLifeBalance' = 'workLifeBalance',
|
||||
'StrategicSession' = 'strategicSession',
|
||||
'PersonalGrowth' = 'personalGrowth',
|
||||
'CareerPlaning' = 'careerPlaning',
|
||||
'ExecutiveCoaching' = 'executiveCoaching',
|
||||
'CareerDevelopment' = 'careerDevelopment',
|
||||
'Networking' = 'networking',
|
||||
'BusinessModelReview' = 'businessModelReview',
|
||||
'Price' = 'price',
|
||||
'Duration' = 'duration'
|
||||
}
|
||||
|
||||
export const INITIAL_FILTER: Filter = {
|
||||
[FilterType.WorkLifeBalance]: false,
|
||||
[FilterType.StrategicSession]: false,
|
||||
[FilterType.PersonalGrowth]: false,
|
||||
[FilterType.CareerPlaning]: false,
|
||||
[FilterType.ExecutiveCoaching]: false,
|
||||
[FilterType.CareerDevelopment]: false,
|
||||
[FilterType.Networking]: false,
|
||||
[FilterType.BusinessModelReview]: false,
|
||||
[FilterType.Price]: [65, 170],
|
||||
[FilterType.Duration]: [60, 120]
|
||||
};
|
||||
|
||||
export const INITIAL_ADD_FILTER: AdditionalFilter = {
|
||||
sort: 'By top views',
|
||||
language: Object.keys(LOCALES)
|
||||
};
|
|
@ -1,2 +1 @@
|
|||
export const HEAD_ROUTES = ['faq', 'experts', 'news'];
|
||||
export const FOOTER_ROUTES = ['faq', 'privacy-policy'];
|
||||
export const HEAD_ROUTES = ['bb-client', 'bb-expert', 'blog'];
|
||||
|
|
|
@ -0,0 +1,136 @@
|
|||
.bb-client {
|
||||
margin-top: 140px
|
||||
}
|
||||
|
||||
.tag-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.tag-item {
|
||||
background: #fff;
|
||||
border-radius: 62px;
|
||||
margin: 12px 8px;
|
||||
color: #5aadcc;
|
||||
padding: 16px;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.b2 {
|
||||
padding: 120px 0 80px;
|
||||
|
||||
h2 {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.b4 {
|
||||
margin-bottom: 30px;
|
||||
|
||||
&-list {
|
||||
margin-top: 200px;
|
||||
margin-bottom: 200px;
|
||||
}
|
||||
|
||||
&-item {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
&-title {
|
||||
font-size: 2rem;
|
||||
color: #2c7873;
|
||||
}
|
||||
|
||||
&-descr {
|
||||
color: #003b46;
|
||||
font-size: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.b4-title, .b5-item {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.b5 {
|
||||
position: relative;
|
||||
margin-top: -65px;
|
||||
|
||||
&-item {
|
||||
background: #fff;
|
||||
height: calc(100% - 120px);
|
||||
margin-top: 100px;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
padding: 120px 16px 16px;
|
||||
border-radius: 16px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
&-img {
|
||||
height: 204px;
|
||||
width: auto;
|
||||
top: 0;
|
||||
left: 50%;
|
||||
position: absolute;
|
||||
-webkit-transform: translate(-50%, -50%);
|
||||
-ms-transform: translate(-50%, -50%);
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
&-text {
|
||||
font-size: 1.5rem;
|
||||
color: #5aadcc;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 36px 0;
|
||||
font-size: 2rem;
|
||||
color: #2c7873;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.b6 {
|
||||
margin: 60px 0 40px;
|
||||
|
||||
&-banner {
|
||||
background: #ffd213;
|
||||
border-radius: 16px;
|
||||
padding: 0 32px;
|
||||
display: flex;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
|
||||
&:after {
|
||||
position: absolute;
|
||||
right: -70px;
|
||||
top: -70px;
|
||||
content: "";
|
||||
width: 170px;
|
||||
height: 170px;
|
||||
display: block;
|
||||
background: url(/images/white-ball.svg) center center no-repeat;
|
||||
background-size: contain;
|
||||
}
|
||||
}
|
||||
|
||||
&-content {
|
||||
width: 45%;
|
||||
color: #2C7873;
|
||||
}
|
||||
|
||||
&-title {
|
||||
font-size: 2rem;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
&-descr {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
&-img {
|
||||
width: 55%;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
.b-slider {
|
||||
margin-top: -105px;
|
||||
|
||||
h2 {
|
||||
margin: 40px 0 20px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.slider {
|
||||
position: relative;
|
||||
padding-bottom: 80px;
|
||||
padding-top: 20px;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
|
||||
&:after {
|
||||
content: "";
|
||||
background: url(/images/slider-nahd.png) center center no-repeat;
|
||||
left: 50%;
|
||||
top: 20px;
|
||||
width: 522px;
|
||||
height: 522px;
|
||||
position: absolute;
|
||||
-webkit-transform: translate(-50%, -5px);
|
||||
-ms-transform: translate(-50%, -5px);
|
||||
transform: translate(-50%, -5px);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&-item {
|
||||
display: inline-flex !important;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.waves-top {
|
||||
position: relative;
|
||||
background: #DFF5FB;
|
||||
margin-bottom: 24px;
|
||||
|
||||
&:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
background-image: url(/images/wave-footer.svg);
|
||||
background-position: center bottom;
|
||||
background-size: contain;
|
||||
background-repeat: repeat-x;
|
||||
top: -59px;
|
||||
width: 100%;
|
||||
height: 59px;
|
||||
}
|
||||
}
|
||||
|
||||
.advice-list {
|
||||
margin: 24px 0 40px;
|
||||
}
|
||||
|
||||
.advice-item {
|
||||
background: #E4F5FA;
|
||||
border-radius: 16px;
|
||||
margin-bottom: 24px;
|
||||
padding: 16px;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.advice-item--with-img {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.advice-img {
|
||||
width: 148px;
|
||||
min-width: 148px;
|
||||
height: auto;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
.advice-title {
|
||||
font-size: 2rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.b3 {
|
||||
margin-bottom: 40px;
|
||||
|
||||
&-item {
|
||||
background: #e0f3f1;
|
||||
height: calc(100% - 120px);
|
||||
margin-bottom: 20px;
|
||||
margin-top: 100px;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
padding: 120px 16px 16px;
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
&-img {
|
||||
position: absolute;
|
||||
height: 204px;
|
||||
width: auto;
|
||||
top: 0;
|
||||
left: 50%;
|
||||
-webkit-transform: translate(-50%, -50%);
|
||||
-ms-transform: translate(-50%, -50%);
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
&-title {
|
||||
color: #000;
|
||||
font-size: 1.5rem;
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
|
||||
&-text {
|
||||
font-size: 1rem;
|
||||
}
|
||||
}
|
||||
|
|
@ -287,6 +287,10 @@ body{
|
|||
align-items: flex-start;
|
||||
width: 100%;
|
||||
|
||||
& > div {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&__inner {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
@ -321,6 +325,7 @@ body{
|
|||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 160%;
|
||||
text-transform: capitalize;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -440,6 +445,10 @@ body{
|
|||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 160%;
|
||||
|
||||
&:hover, &:active {
|
||||
color: #003B46 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-back {
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
.banner {
|
||||
text-align: center;
|
||||
margin-bottom: -80px;
|
||||
|
||||
&-faq {
|
||||
h1 {
|
||||
font-size: 2.93rem;
|
||||
margin-top: 120px;
|
||||
color: #2C7873;
|
||||
}
|
||||
}
|
||||
|
||||
&-note {
|
||||
font-size: 1.5rem;
|
||||
color: #4e7c86;
|
||||
}
|
||||
}
|
||||
|
||||
.mb-4 {
|
||||
margin-bottom: 1.5rem!important;
|
||||
}
|
||||
|
||||
.store-buttons {
|
||||
display: flex;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.store-button {
|
||||
color: #fff;
|
||||
font-size: 1.5rem;
|
||||
line-height: 1.5rem;
|
||||
text-decoration: none;
|
||||
background: #5AADCC;
|
||||
border-radius: 62px;
|
||||
padding: 21px 15px 21px 73px;
|
||||
margin: 0 12px;
|
||||
transition: .3s all ease;
|
||||
animation: pulse;
|
||||
animation-duration: 2s;
|
||||
position: relative;
|
||||
|
||||
&:before {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
position: absolute;
|
||||
left: 24px;
|
||||
transform: translate(0, -50%);
|
||||
}
|
||||
|
||||
&:after {
|
||||
width: 1px;
|
||||
height: 42px;
|
||||
position: absolute;
|
||||
left: 64px;
|
||||
background: #fff;
|
||||
transform: translate(0, -50%);
|
||||
}
|
||||
|
||||
&:after, &:before {
|
||||
display: block;
|
||||
top: 50%;
|
||||
content: "";
|
||||
}
|
||||
|
||||
&.phone:before {
|
||||
background: url(/images/call-outline-white.svg) center center no-repeat;
|
||||
background-size: contain;
|
||||
}
|
||||
}
|
||||
|
||||
.mb-5 {
|
||||
margin-bottom: 3rem!important;
|
||||
}
|
||||
|
||||
.advice {
|
||||
&-item {
|
||||
background: #E4F5FA;
|
||||
border-radius: 16px;
|
||||
margin-bottom: 24px;
|
||||
padding: 16px;
|
||||
font-size: 1.5rem;
|
||||
|
||||
&--with-img {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
&-img {
|
||||
width: 148px;
|
||||
min-width: 148px;
|
||||
height: auto;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
&-title {
|
||||
font-size: 2rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
}
|
|
@ -4,6 +4,9 @@
|
|||
@import "_header.scss";
|
||||
@import "_menu-mobile.scss";
|
||||
@import "_main.scss";
|
||||
@import "_bb-experts.scss";
|
||||
@import "_bb-clients.scss";
|
||||
@import "_faq.scss";
|
||||
@import "_footer.scss";
|
||||
@import "_cols.scss";
|
||||
@import "_pages.scss";
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
export type Filter = Record<string, any>;
|
||||
import { Tag } from './tags';
|
||||
|
||||
// export type Filter = {
|
||||
// themesTagIds: number[];
|
||||
// priceFrom?: number | null;
|
||||
// priceTo?: number | null;
|
||||
// durationFrom?: number | null;
|
||||
// durationTo?: number | null;
|
||||
// };
|
||||
// export type Filter = Record<string, any>;
|
||||
|
||||
export type GeneralFilter = Filter & AdditionalFilter;
|
||||
|
||||
export type Filter = {
|
||||
themesTagIds?: number[];
|
||||
priceFrom?: number | null;
|
||||
priceTo?: number | null;
|
||||
durationFrom?: number | null;
|
||||
durationTo?: number | null;
|
||||
};
|
||||
|
||||
export type AdditionalFilter = {
|
||||
text?: string;
|
||||
|
@ -14,14 +18,6 @@ export type AdditionalFilter = {
|
|||
language?: string[];
|
||||
};
|
||||
|
||||
export type Tag = {
|
||||
id: number;
|
||||
groupId: number;
|
||||
name: string
|
||||
couchCount?: number;
|
||||
group?: string | null;
|
||||
};
|
||||
|
||||
export type File = {
|
||||
id: number;
|
||||
fileType: string;
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
export type Tag = {
|
||||
id: number;
|
||||
groupId: number;
|
||||
name: string
|
||||
couchCount?: number;
|
||||
group?: string | null;
|
||||
};
|
||||
|
||||
export type ThemeGroups = {
|
||||
id: number;
|
||||
name: string;
|
||||
tags: Tag[];
|
||||
};
|
||||
|
||||
export type SearchData = {
|
||||
themesGroups: ThemeGroups[],
|
||||
sessionCostMin: number;
|
||||
sessionCostMax: number;
|
||||
sessionDurationMin: number;
|
||||
sessionDurationMax: number;
|
||||
};
|
|
@ -0,0 +1,103 @@
|
|||
import { SearchData } from '../types/tags';
|
||||
import { AdditionalFilter, Filter } from '../types/experts';
|
||||
|
||||
export const getDefaultFilter = (searchData: SearchData | null): Filter => {
|
||||
const themesTagIds = searchData?.themesGroups?.reduce<number[]>((result, { tags }) => {
|
||||
const t = tags?.map(({ id }) => id) || [];
|
||||
|
||||
return t ? [
|
||||
...result,
|
||||
...t
|
||||
] : result;
|
||||
}, []);
|
||||
|
||||
return {
|
||||
themesTagIds,
|
||||
priceFrom: null,
|
||||
priceTo: null,
|
||||
durationFrom: null,
|
||||
durationTo: null
|
||||
} as Filter;
|
||||
};
|
||||
|
||||
export const getFilter = (searchData: SearchData | null, searchParams?: { [key: string]: string | string[] | undefined }): Filter => {
|
||||
const filter = getDefaultFilter(searchData);
|
||||
|
||||
if (searchParams) {
|
||||
const { themesTagIds, priceFrom, priceTo, durationFrom, durationTo } = searchParams;
|
||||
|
||||
if (themesTagIds) {
|
||||
if (Array.isArray(themesTagIds) && themesTagIds?.length > 0) {
|
||||
filter.themesTagIds = themesTagIds.map((id) => +id);
|
||||
}
|
||||
|
||||
if (typeof themesTagIds === 'string') {
|
||||
filter.themesTagIds = [+themesTagIds];
|
||||
}
|
||||
}
|
||||
|
||||
if (priceFrom) {
|
||||
filter.priceFrom = +priceFrom;
|
||||
}
|
||||
|
||||
if (priceTo) {
|
||||
filter.priceTo = +priceTo;
|
||||
}
|
||||
|
||||
if (durationFrom) {
|
||||
filter.durationFrom = +durationFrom;
|
||||
}
|
||||
|
||||
if (durationTo) {
|
||||
filter.durationTo = +durationTo;
|
||||
}
|
||||
}
|
||||
|
||||
return filter;
|
||||
};
|
||||
|
||||
export const getObjectByFilter = (searchParams?: any): Filter | undefined => {
|
||||
const filter: Filter = {};
|
||||
|
||||
let tags = searchParams?.getAll('themesTagIds');
|
||||
|
||||
if (tags && tags.length > 0) {
|
||||
filter.themesTagIds = tags.map((id) => Number(id));
|
||||
}
|
||||
|
||||
if (searchParams?.has('priceFrom')) {
|
||||
filter.priceFrom = Number(searchParams.get('priceFrom'));
|
||||
}
|
||||
|
||||
if (searchParams?.has('priceTo')) {
|
||||
filter.priceTo = Number(searchParams.get('priceTo'));
|
||||
}
|
||||
|
||||
if (searchParams?.has('durationFrom')) {
|
||||
filter.durationFrom = Number(searchParams.get('durationFrom'));
|
||||
}
|
||||
|
||||
if (searchParams?.has('durationTo')) {
|
||||
filter.durationTo = Number(searchParams.get('durationTo'));
|
||||
}
|
||||
|
||||
return filter;
|
||||
};
|
||||
|
||||
export const getObjectByAdditionalFilter = (searchParams?: any): AdditionalFilter => {
|
||||
const additionalFilter: AdditionalFilter = {};
|
||||
|
||||
if (searchParams?.has('text')) {
|
||||
additionalFilter.text = searchParams.get('text');
|
||||
}
|
||||
|
||||
if (searchParams?.has('sort')) {
|
||||
additionalFilter.sort = searchParams.get('sort');
|
||||
}
|
||||
|
||||
if (searchParams?.has('language')) {
|
||||
additionalFilter.language = searchParams.getAll('language');
|
||||
}
|
||||
|
||||
return additionalFilter;
|
||||
};
|
|
@ -0,0 +1,23 @@
|
|||
'use client';
|
||||
|
||||
import { AUTH_TOKEN_KEY } from '../../constants/common';
|
||||
|
||||
export function checkAuthToken() {
|
||||
return !!getAuthToken();
|
||||
}
|
||||
|
||||
export function getAuthToken() {
|
||||
return 'tr';
|
||||
}
|
||||
|
||||
// export function getAuthToken() {
|
||||
// return localStorage.getItem(AUTH_TOKEN_KEY);
|
||||
// }
|
||||
//
|
||||
// export function removeAuthToken() {
|
||||
// localStorage.removeItem(AUTH_TOKEN_KEY);
|
||||
// }
|
||||
//
|
||||
// export function setAuthToken(token: string) {
|
||||
// localStorage.setItem(AUTH_TOKEN_KEY, token);
|
||||
// }
|