Initial commit
This commit is contained in:
1
.env.production
Normal file
1
.env.production
Normal file
@@ -0,0 +1 @@
|
||||
DISABLE_ESLINT_PLUGIN=true
|
||||
62
.gitea/workflows/build.yml
Normal file
62
.gitea/workflows/build.yml
Normal file
@@ -0,0 +1,62 @@
|
||||
name: Build
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
branch:
|
||||
description: 'Branch to build'
|
||||
required: true
|
||||
default: 'main'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
|
||||
steps:
|
||||
- name: Checkout branch
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ gitea.event.inputs.branch }}
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 24
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
set -euo pipefail
|
||||
npm install --no-audit --silent 2>&1 | tee install.log
|
||||
env:
|
||||
NODE_OPTIONS: '--max-old-space-size=4096'
|
||||
|
||||
- name: Build (react-scripts build)
|
||||
env:
|
||||
CI: 'false'
|
||||
NODE_OPTIONS: '--max-old-space-size=4096'
|
||||
run: |
|
||||
set -euo pipefail
|
||||
npm run build 2>&1 | tee build.log
|
||||
timeout-minutes: 5
|
||||
|
||||
- name: Verify build folder exists
|
||||
run: test -d build || (echo "No build folder. Check build logs above."; exit 1)
|
||||
|
||||
- name: Upload logs on failure
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: build-logs
|
||||
path: |
|
||||
install.log
|
||||
build.log
|
||||
npm-debug.log*
|
||||
if-no-files-found: ignore
|
||||
|
||||
- name: Build completed
|
||||
if: success()
|
||||
run: echo "Build completed successfully"
|
||||
41
package.json
Normal file
41
package.json
Normal file
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"name": "linkedin-ukraine-clone",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-scripts": "^5.0.1",
|
||||
"lucide-react": "^0.400.0",
|
||||
"framer-motion": "^11.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"tailwindcss": "^3.4.0",
|
||||
"postcss": "^8.4.0",
|
||||
"autoprefixer": "^10.4.0"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
"react-app",
|
||||
"react-app/jest"
|
||||
]
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
}
|
||||
}
|
||||
6
postcss.config.js
Normal file
6
postcss.config.js
Normal file
@@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBoZWlnaHQ9IjEyOCIgd2lkdGg9IjI0Ij48ZGVmcz48c3ltYm9sIGlkPSJhIj48cGF0aCBkPSJNMTQgMTIuNjdMMTEuMTMgOS44YTUgNSAwIDEwLTEuMzMgMS4zM0wxMi42NyAxNHpNMy44OCA3QTMuMTMgMy4xMyAwIDExNyAxMC4xMyAzLjEzIDMuMTMgMCAwMTMuODggN3oiLz48L3N5bWJvbD48c3ltYm9sIGlkPSJiIj48cGF0aCBkPSJNMjEgMTkuNjdsLTUuNDQtNS40NGE3IDcgMCAxMC0xLjMzIDEuMzNMMTkuNjcgMjF6bS0xMS00LjU0QTUuMTMgNS4xMyAwIDExMTUuMTMgMTAgNS4xMyA1LjEzIDAgMDExMCAxNS4xM3oiLz48L3N5bWJvbD48L2RlZnM+PHVzZSB4bGluazpocmVmPSIjYSIgZmlsbD0iI2ZmZiIgc3Ryb2tlLW9wYWNpdHk9IjAiLz48dXNlIHhsaW5rOmhyZWY9IiNhIiB5PSIxNiIvPjx1c2UgeGxpbms6aHJlZj0iI2EiIHk9IjMyIiBmaWxsLW9wYWNpdHk9Ii42Ii8+PHVzZSB4bGluazpocmVmPSIjYiIgeT0iNDgiIGZpbGw9IiNmZmYiIHN0cm9rZS1vcGFjaXR5PSIwIi8+PHVzZSB4bGluazpocmVmPSIjYiIgeT0iNzIiLz48dXNlIHhsaW5rOmhyZWY9IiNiIiB5PSI5NiIgZmlsbC1vcGFjaXR5PSIuNiIvPjwvc3ZnPg==
|
||||
@@ -0,0 +1 @@
|
||||
PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBoZWlnaHQ9IjEyOCIgd2lkdGg9IjI0Ij48ZGVmcz48c3ltYm9sIGlkPSJhIj48cGF0aCBkPSJNOCA0YTIgMiAwIDEwMiAyIDIgMiAwIDAwLTItMnptMCAzLjEzQTEuMTMgMS4xMyAwIDExOS4xMyA2IDEuMTMgMS4xMyAwIDAxOCA3LjEzek04IDFhNSA1IDAgMDAtNSA1IDUuMzcgNS4zNyAwIDAwLjQxIDJzMi41IDUgMy44MSA3LjUyQS44Ni44NiAwIDAwOCAxNmEuODYuODYgMCAwMC43OC0uNDhDMTAuMDkgMTMgMTIuNTkgOCAxMi41OSA4QTUuMzcgNS4zNyAwIDAwMTMgNmE1IDUgMCAwMC01LTV6bTIuODggNi4yNEw4IDEyLjkyIDUuMTIgNy4yNEEzLjQ5IDMuNDkgMCAwMTQuODggNmEzLjEzIDMuMTMgMCAwMTYuMjUgMCAzLjQ5IDMuNDkgMCAwMS0uMjUgMS4yNHoiLz48L3N5bWJvbD48c3ltYm9sIGlkPSJiIj48cGF0aCBkPSJNMTIgNmMtMS43IDAtMyAxLjMtMyAzczEuMyAzIDMgMyAzLTEuMyAzLTMtMS4zLTMtMy0zem0wIDUuMWMtMS4yIDAtMi4xLTEtMi4xLTIuMSAwLTEuMiAxLTIuMSAyLjEtMi4xIDEuMiAwIDIuMSAxIDIuMSAyLjEgMCAxLjItLjkgMi4xLTIuMSAyLjF6bTAtNy4yYzIuOCAwIDUuMSAyLjMgNS4xIDUuMSAwIC43LS4yIDEuNS0uNSAyLjJMMTIgMjBsLTQuNi04LjhjLS40LS43LS41LTEuNS0uNS0yLjIgMC0yLjggMi4zLTUuMSA1LjEtNS4xTTEyIDJDOC4xIDIgNSA1LjEgNSA5YzAgMSAuMiAyLjEuNyAzbDUuNiAxMC41Yy4yLjQuNy42IDEuMi40LjItLjEuMy0uMi40LS40TDE4LjMgMTJjMS43LTMuNS4yLTcuNy0zLjMtOS4zLS45LS41LTItLjctMy0uN3oiLz48L3N5bWJvbD48L2RlZnM+PHVzZSB4bGluazpocmVmPSIjYSIgZmlsbD0iI2ZmZiIgc3Ryb2tlLW9wYWNpdHk9IjAiLz48dXNlIHhsaW5rOmhyZWY9IiNhIiB5PSIxNiIvPjx1c2UgeGxpbms6aHJlZj0iI2EiIHk9IjMyIiBmaWxsLW9wYWNpdHk9Ii42Ii8+PHVzZSB4bGluazpocmVmPSIjYiIgeT0iNDgiIGZpbGw9IiNmZmYiIHN0cm9rZS1vcGFjaXR5PSIwIi8+PHVzZSB4bGluazpocmVmPSIjYiIgeT0iNzIiLz48dXNlIHhsaW5rOmhyZWY9IiNiIiB5PSI5NiIgZmlsbC1vcGFjaXR5PSIuNiIvPjwvc3ZnPg==
|
||||
File diff suppressed because one or more lines are too long
1235
public/index.html
Normal file
1235
public/index.html
Normal file
File diff suppressed because it is too large
Load Diff
34
src/App.js
Normal file
34
src/App.js
Normal file
@@ -0,0 +1,34 @@
|
||||
import React from 'react';
|
||||
import CookieBanner from './components/CookieBanner';
|
||||
import Header from './components/Header';
|
||||
import Hero from './components/Hero';
|
||||
import JobSearch from './components/JobSearch';
|
||||
import PostJobs from './components/PostJobs';
|
||||
import DiscoverPrograms from './components/DiscoverPrograms';
|
||||
import KeepInTouch from './components/KeepInTouch';
|
||||
import ConnectWithPeople from './components/ConnectWithPeople';
|
||||
import GetSkills from './components/GetSkills';
|
||||
import WhoIsLinkedIn from './components/WhoIsLinkedIn';
|
||||
import Footer from './components/Footer';
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<div className="App">
|
||||
<CookieBanner />
|
||||
<Header />
|
||||
<main>
|
||||
<Hero />
|
||||
<JobSearch />
|
||||
<PostJobs />
|
||||
<DiscoverPrograms />
|
||||
<KeepInTouch />
|
||||
<ConnectWithPeople />
|
||||
<GetSkills />
|
||||
<WhoIsLinkedIn />
|
||||
</main>
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
71
src/components/ConnectWithPeople.js
Normal file
71
src/components/ConnectWithPeople.js
Normal file
@@ -0,0 +1,71 @@
|
||||
import React from 'react';
|
||||
import { motion, useReducedMotion } from 'framer-motion';
|
||||
|
||||
const fadeUpPreset = (delay = 0, duration = 1.2) => ({
|
||||
initial: { opacity: 0, y: 20 },
|
||||
whileInView: { opacity: 1, y: 0 },
|
||||
viewport: { once: true, amount: 0.2 },
|
||||
transition: { delay, duration, ease: "easeOut" }
|
||||
});
|
||||
|
||||
const ConnectWithPeople = () => {
|
||||
const shouldReduce = useReducedMotion();
|
||||
|
||||
if (shouldReduce) {
|
||||
return (
|
||||
<section className="py-16 bg-white">
|
||||
<div className="section-container">
|
||||
<div className="grid lg:grid-cols-2 gap-12 items-center">
|
||||
<div>
|
||||
<h2 className="text-3xl lg:text-4xl font-light text-linkedin-text mb-6">
|
||||
Поділіться тим, що ви шукаєте роботу, з потрібними людьми
|
||||
</h2>
|
||||
<p className="text-linkedin-gray mb-8">
|
||||
За допомогою функції #OpenToWork ви можете приватно повідомити рекрутерів або публічно поділитися з мережею LinkedIn, що ви шукаєте нові можливості професійного розвитку.
|
||||
</p>
|
||||
</div>
|
||||
<div className="bg-gray-100 rounded-lg h-64 flex items-center justify-center">
|
||||
<div className="w-32 h-32 bg-linkedin-blue rounded-full flex items-center justify-center">
|
||||
<svg className="w-16 h-16 text-white" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<motion.section
|
||||
{...fadeUpPreset(0.1, 1.0)}
|
||||
className="py-16 bg-white"
|
||||
>
|
||||
<div className="section-container">
|
||||
<div className="grid lg:grid-cols-2 gap-12 items-center">
|
||||
<motion.div {...fadeUpPreset(0.2, 1.0)}>
|
||||
<h2 className="text-3xl lg:text-4xl font-light text-linkedin-text mb-6">
|
||||
Поділіться тим, що ви шукаєте роботу, з потрібними людьми
|
||||
</h2>
|
||||
<p className="text-linkedin-gray mb-8">
|
||||
За допомогою функції #OpenToWork ви можете приватно повідомити рекрутерів або публічно поділитися з мережею LinkedIn, що ви шукаєте нові можливості професійного розвитку.
|
||||
</p>
|
||||
</motion.div>
|
||||
<motion.div
|
||||
{...fadeUpPreset(0.4, 1.0)}
|
||||
className="bg-gray-100 rounded-lg h-64 flex items-center justify-center"
|
||||
>
|
||||
<div className="w-32 h-32 bg-linkedin-blue rounded-full flex items-center justify-center">
|
||||
<svg className="w-16 h-16 text-white" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/>
|
||||
</svg>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
</div>
|
||||
</motion.section>
|
||||
);
|
||||
};
|
||||
|
||||
export default ConnectWithPeople;
|
||||
43
src/components/CookieBanner.js
Normal file
43
src/components/CookieBanner.js
Normal file
@@ -0,0 +1,43 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Info } from 'lucide-react';
|
||||
|
||||
const CookieBanner = () => {
|
||||
const [isVisible, setIsVisible] = useState(true);
|
||||
|
||||
if (!isVisible) return null;
|
||||
|
||||
return (
|
||||
<div className="bg-slate-600 text-white p-4 text-sm">
|
||||
<div className="section-container">
|
||||
<div className="flex items-start gap-3">
|
||||
<Info className="w-5 h-5 mt-0.5 flex-shrink-0" />
|
||||
<div className="flex-1">
|
||||
<h3 className="font-semibold mb-2">LinkedIn поважає вашу конфіденційність</h3>
|
||||
<p className="mb-4 leading-relaxed">
|
||||
LinkedIn та треті сторони використовують важливі та несуттєві файли cookie для надання, захисту, аналізу та вдосконалення наших Послуг, а також для показу відповідних оголошень (включаючи <span className="underline">професійні та оголошення про роботу</span>) на LinkedIn або поза його межами. Дізнатися більше про нашу <span className="underline">Політика щодо файлів cookie</span>.
|
||||
</p>
|
||||
<p className="mb-4">
|
||||
Виберіть «Прийняти» щоб погодитися, або «Відхилити», щоб не дозволити використовувати несуттєві файли cookie. Ви зможете оновити свій вибір у своїх <span className="underline">налаштування</span> у будь-який час.
|
||||
</p>
|
||||
<div className="flex gap-3">
|
||||
<button
|
||||
onClick={() => setIsVisible(false)}
|
||||
className="bg-white text-slate-600 px-6 py-2 rounded font-semibold hover:bg-gray-100 transition-colors"
|
||||
>
|
||||
Прийняти
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setIsVisible(false)}
|
||||
className="border border-white text-white px-6 py-2 rounded font-semibold hover:bg-white hover:text-slate-600 transition-colors"
|
||||
>
|
||||
Відхилити
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CookieBanner;
|
||||
92
src/components/DiscoverPrograms.js
Normal file
92
src/components/DiscoverPrograms.js
Normal file
@@ -0,0 +1,92 @@
|
||||
import React from 'react';
|
||||
import { motion, useReducedMotion } from 'framer-motion';
|
||||
|
||||
const fadeUpPreset = (delay = 0, duration = 1.2) => ({
|
||||
initial: { opacity: 0, y: 20 },
|
||||
whileInView: { opacity: 1, y: 0 },
|
||||
viewport: { once: true, amount: 0.2 },
|
||||
transition: { delay, duration, ease: "easeOut" }
|
||||
});
|
||||
|
||||
const DiscoverPrograms = () => {
|
||||
const shouldReduce = useReducedMotion();
|
||||
|
||||
const programs = [
|
||||
'Програми корпоративного навчання',
|
||||
'Програми обмінного навчання',
|
||||
'Програми обмінного CRM',
|
||||
'Системи управління навчанням',
|
||||
'Програми обмінного для розробників',
|
||||
'Програми обмінного для аналітики даних',
|
||||
'Програми обмінного для управління проектами',
|
||||
'Програми обмінного для соціальних мереж',
|
||||
'Програми обмінного для управління командою',
|
||||
'Програми обмінного для управління часом',
|
||||
'Програми обмінного для управління фінансами',
|
||||
'Показати все'
|
||||
];
|
||||
|
||||
if (shouldReduce) {
|
||||
return (
|
||||
<section className="py-16 bg-white">
|
||||
<div className="section-container">
|
||||
<div className="max-w-2xl">
|
||||
<h2 className="text-3xl lg:text-4xl font-light text-linkedin-text mb-6">
|
||||
Відкрийте для себе найкращі програми навчальні інструменти
|
||||
</h2>
|
||||
<p className="text-linkedin-gray mb-8">
|
||||
Щоб знайти найкращі навчальні програми для вас або вашої команди, скористайтеся нашими рекомендаціями, які базуються на ваших інтересах та досвіді.
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-3">
|
||||
{programs.map((program, index) => (
|
||||
<button key={index} className="tag-button">
|
||||
{program}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<motion.section
|
||||
{...fadeUpPreset(0.1, 1.0)}
|
||||
className="py-16 bg-white"
|
||||
>
|
||||
<div className="section-container">
|
||||
<div className="max-w-2xl">
|
||||
<motion.h2
|
||||
{...fadeUpPreset(0.2, 1.0)}
|
||||
className="text-3xl lg:text-4xl font-light text-linkedin-text mb-6"
|
||||
>
|
||||
Відкрийте для себе найкращі програми навчальні інструменти
|
||||
</motion.h2>
|
||||
<motion.p
|
||||
{...fadeUpPreset(0.3, 1.0)}
|
||||
className="text-linkedin-gray mb-8"
|
||||
>
|
||||
Щоб знайти найкращі навчальні програми для вас або вашої команди, скористайтеся нашими рекомендаціями, які базуються на ваших інтересах та досвіді.
|
||||
</motion.p>
|
||||
<motion.div
|
||||
{...fadeUpPreset(0.4, 1.0)}
|
||||
className="flex flex-wrap gap-3"
|
||||
>
|
||||
{programs.map((program, index) => (
|
||||
<motion.button
|
||||
key={index}
|
||||
{...fadeUpPreset(0.5 + index * 0.03, 0.6)}
|
||||
className="tag-button"
|
||||
>
|
||||
{program}
|
||||
</motion.button>
|
||||
))}
|
||||
</motion.div>
|
||||
</div>
|
||||
</div>
|
||||
</motion.section>
|
||||
);
|
||||
};
|
||||
|
||||
export default DiscoverPrograms;
|
||||
120
src/components/Footer.js
Normal file
120
src/components/Footer.js
Normal file
@@ -0,0 +1,120 @@
|
||||
import React from 'react';
|
||||
|
||||
const Footer = () => {
|
||||
const footerSections = [
|
||||
{
|
||||
title: 'Загальна інформація',
|
||||
links: [
|
||||
'Про нас',
|
||||
'Кар\'єра',
|
||||
'Рекламні послуги',
|
||||
'Малий бізнес',
|
||||
'Центр довіри та безпеки'
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Можливості LinkedIn',
|
||||
links: [
|
||||
'LinkedIn Premium',
|
||||
'Рішення для талантів',
|
||||
'Маркетингові рішення',
|
||||
'Рішення для продажів',
|
||||
'Центр безпеки'
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Спільнота',
|
||||
links: [
|
||||
'Професійна спільнота',
|
||||
'Політики та рекомендації',
|
||||
'Конфіденційність та умови',
|
||||
'Мобільний додаток',
|
||||
'Довідка'
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Каталоги',
|
||||
links: [
|
||||
'Учасники',
|
||||
'Вакансії',
|
||||
'Компанії',
|
||||
'Рекомендовані',
|
||||
'Послуги',
|
||||
'Продукти',
|
||||
'Поради',
|
||||
'Люди також переглядають',
|
||||
'Навчання',
|
||||
'Каталог тем',
|
||||
'Сьогодні на LinkedIn',
|
||||
'Ігри'
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
const bottomLinks = [
|
||||
'Загальна інформація',
|
||||
'Доступність',
|
||||
'Угода про користування',
|
||||
'Політика конфіденційності',
|
||||
'Політика щодо файлів cookie',
|
||||
'Політика захисту авторських прав',
|
||||
'Політика щодо торгових марок',
|
||||
'Гостьовий контроль',
|
||||
'Правила спільноти',
|
||||
'Мова'
|
||||
];
|
||||
|
||||
return (
|
||||
<footer className="bg-linkedin-light-gray border-t border-linkedin-border">
|
||||
<div className="section-container py-12">
|
||||
{/* Logo */}
|
||||
<div className="mb-8">
|
||||
<svg className="w-8 h-8 text-linkedin-blue" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
{/* Footer Links Grid */}
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-8 mb-8">
|
||||
{footerSections.map((section, index) => (
|
||||
<div key={index}>
|
||||
<h3 className="font-semibold text-linkedin-text mb-4">{section.title}</h3>
|
||||
<ul className="space-y-2">
|
||||
{section.links.map((link, linkIndex) => (
|
||||
<li key={linkIndex}>
|
||||
<a
|
||||
href="#"
|
||||
className="text-sm text-linkedin-gray hover:text-linkedin-blue transition-colors duration-200"
|
||||
>
|
||||
{link}
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Bottom Links */}
|
||||
<div className="border-t border-linkedin-border pt-8">
|
||||
<div className="flex flex-wrap gap-4 text-xs text-linkedin-gray mb-4">
|
||||
{bottomLinks.map((link, index) => (
|
||||
<a
|
||||
key={index}
|
||||
href="#"
|
||||
className="hover:text-linkedin-blue transition-colors duration-200"
|
||||
>
|
||||
{link}
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
<p className="text-xs text-linkedin-gray">
|
||||
© 2025
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
);
|
||||
};
|
||||
|
||||
export default Footer;
|
||||
70
src/components/GetSkills.js
Normal file
70
src/components/GetSkills.js
Normal file
@@ -0,0 +1,70 @@
|
||||
import React from 'react';
|
||||
import { motion, useReducedMotion } from 'framer-motion';
|
||||
|
||||
const fadeUpPreset = (delay = 0, duration = 1.2) => ({
|
||||
initial: { opacity: 0, y: 20 },
|
||||
whileInView: { opacity: 1, y: 0 },
|
||||
viewport: { once: true, amount: 0.2 },
|
||||
transition: { delay, duration, ease: "easeOut" }
|
||||
});
|
||||
|
||||
const GetSkills = () => {
|
||||
const shouldReduce = useReducedMotion();
|
||||
|
||||
if (shouldReduce) {
|
||||
return (
|
||||
<section className="py-16 bg-linkedin-light-gray">
|
||||
<div className="section-container">
|
||||
<div className="grid lg:grid-cols-2 gap-12 items-center">
|
||||
<div>
|
||||
<h2 className="text-3xl lg:text-4xl font-light text-linkedin-text mb-6">
|
||||
Встановлюйте контакт з людьми, які можуть допомогти
|
||||
</h2>
|
||||
<button className="btn-secondary">
|
||||
Знайти людей, яких знаєте
|
||||
</button>
|
||||
</div>
|
||||
<div>
|
||||
<h2 className="text-3xl lg:text-4xl font-light text-linkedin-text mb-6">
|
||||
Здобудьте навички, необхідні для досягнення успіху
|
||||
</h2>
|
||||
<p className="text-linkedin-gray mb-8">
|
||||
Виберіть тему, яку ви хочете вивчити
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<motion.section
|
||||
{...fadeUpPreset(0.1, 1.0)}
|
||||
className="py-16 bg-linkedin-light-gray"
|
||||
>
|
||||
<div className="section-container">
|
||||
<div className="grid lg:grid-cols-2 gap-12 items-center">
|
||||
<motion.div {...fadeUpPreset(0.2, 1.0)}>
|
||||
<h2 className="text-3xl lg:text-4xl font-light text-linkedin-text mb-6">
|
||||
Встановлюйте контакт з людьми, які можуть допомогти
|
||||
</h2>
|
||||
<button className="btn-secondary">
|
||||
Знайти людей, яких знаєте
|
||||
</button>
|
||||
</motion.div>
|
||||
<motion.div {...fadeUpPreset(0.4, 1.0)}>
|
||||
<h2 className="text-3xl lg:text-4xl font-light text-linkedin-text mb-6">
|
||||
Здобудьте навички, необхідні для досягнення успіху
|
||||
</h2>
|
||||
<p className="text-linkedin-gray mb-8">
|
||||
Виберіть тему, яку ви хочете вивчити
|
||||
</p>
|
||||
</motion.div>
|
||||
</div>
|
||||
</div>
|
||||
</motion.section>
|
||||
);
|
||||
};
|
||||
|
||||
export default GetSkills;
|
||||
93
src/components/Header.js
Normal file
93
src/components/Header.js
Normal file
@@ -0,0 +1,93 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Menu, X } from 'lucide-react';
|
||||
|
||||
const Header = () => {
|
||||
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
|
||||
|
||||
const navItems = [
|
||||
{ label: 'Статті', href: '#' },
|
||||
{ label: 'Люди', href: '#' },
|
||||
{ label: 'Learning', href: '#' },
|
||||
{ label: 'Вакансії', href: '#' },
|
||||
{ label: 'Ігри', href: '#' },
|
||||
{ label: 'Завантажити додат', href: '#' }
|
||||
];
|
||||
|
||||
return (
|
||||
<header className="bg-white border-b border-linkedin-border sticky top-0 z-50">
|
||||
<div className="section-container">
|
||||
<div className="flex items-center justify-between h-16">
|
||||
{/* Logo */}
|
||||
<div className="flex items-center">
|
||||
<svg className="w-8 h-8 text-linkedin-blue" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/>
|
||||
</svg>
|
||||
<span className="ml-2 text-xl font-bold text-linkedin-blue">LinkedIn</span>
|
||||
</div>
|
||||
|
||||
{/* Desktop Navigation */}
|
||||
<nav className="hidden lg:flex items-center space-x-8">
|
||||
{navItems.map((item, index) => (
|
||||
<a
|
||||
key={index}
|
||||
href={item.href}
|
||||
className="text-linkedin-gray hover:text-linkedin-blue transition-colors duration-200 font-medium"
|
||||
>
|
||||
{item.label}
|
||||
</a>
|
||||
))}
|
||||
</nav>
|
||||
|
||||
{/* Auth Buttons */}
|
||||
<div className="hidden lg:flex items-center space-x-4">
|
||||
<button className="text-linkedin-gray hover:text-linkedin-blue font-semibold px-4 py-2 rounded transition-colors duration-200">
|
||||
Увійти
|
||||
</button>
|
||||
<button className="btn-primary">
|
||||
Зареєструйтеся зараз
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Mobile Menu Button */}
|
||||
<button
|
||||
className="lg:hidden p-2"
|
||||
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
|
||||
>
|
||||
{isMobileMenuOpen ? (
|
||||
<X className="w-6 h-6 text-linkedin-gray" />
|
||||
) : (
|
||||
<Menu className="w-6 h-6 text-linkedin-gray" />
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Mobile Menu */}
|
||||
{isMobileMenuOpen && (
|
||||
<div className="lg:hidden border-t border-linkedin-border py-4">
|
||||
<nav className="flex flex-col space-y-4">
|
||||
{navItems.map((item, index) => (
|
||||
<a
|
||||
key={index}
|
||||
href={item.href}
|
||||
className="text-linkedin-gray hover:text-linkedin-blue transition-colors duration-200 font-medium"
|
||||
>
|
||||
{item.label}
|
||||
</a>
|
||||
))}
|
||||
<div className="flex flex-col space-y-3 pt-4 border-t border-linkedin-border">
|
||||
<button className="text-linkedin-gray hover:text-linkedin-blue font-semibold text-left">
|
||||
Увійти
|
||||
</button>
|
||||
<button className="btn-primary text-center">
|
||||
Зареєструйтеся зараз
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
};
|
||||
|
||||
export default Header;
|
||||
116
src/components/Hero.js
Normal file
116
src/components/Hero.js
Normal file
@@ -0,0 +1,116 @@
|
||||
import React from 'react';
|
||||
import { motion, useReducedMotion } from 'framer-motion';
|
||||
|
||||
const fadeUpPreset = (delay = 0, duration = 1.2) => ({
|
||||
initial: { opacity: 0, y: 20 },
|
||||
whileInView: { opacity: 1, y: 0 },
|
||||
viewport: { once: true, amount: 0.2 },
|
||||
transition: { delay, duration, ease: "easeOut" }
|
||||
});
|
||||
|
||||
const Hero = () => {
|
||||
const shouldReduce = useReducedMotion();
|
||||
|
||||
if (shouldReduce) {
|
||||
return (
|
||||
<section className="bg-linkedin-light-gray py-16 lg:py-24">
|
||||
<div className="section-container">
|
||||
<div className="grid lg:grid-cols-2 gap-12 items-center">
|
||||
<div>
|
||||
<h1 className="text-4xl lg:text-5xl font-light text-linkedin-text mb-6 leading-tight">
|
||||
Ласкаво просимо до професійної спільноти!
|
||||
</h1>
|
||||
<div className="space-y-4">
|
||||
<button className="btn-primary w-full sm:w-auto">
|
||||
Приєднатися зараз
|
||||
</button>
|
||||
<div className="flex items-center gap-4">
|
||||
<span className="text-sm text-linkedin-gray">або</span>
|
||||
<button className="text-linkedin-blue hover:underline font-semibold">
|
||||
Увійти
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-sm text-linkedin-gray mt-6">
|
||||
Умови та додаткові умови конфіденційності застосовуються.
|
||||
</p>
|
||||
<p className="text-sm text-linkedin-gray mt-2">
|
||||
Цей сайт захищений reCAPTCHA та застосовуються Політика конфіденційності та Умови обслуговування Google.
|
||||
</p>
|
||||
<p className="text-sm text-linkedin-gray mt-4">
|
||||
Вперше на LinkedIn? <a href="#" className="text-linkedin-blue hover:underline">Приєднайтеся зараз</a>
|
||||
</p>
|
||||
</div>
|
||||
<div className="relative">
|
||||
<div className="bg-white rounded-lg p-8 shadow-lg">
|
||||
<div className="w-full h-64 bg-gradient-to-br from-blue-100 to-orange-100 rounded-lg flex items-center justify-center">
|
||||
<div className="text-center">
|
||||
<div className="w-16 h-16 bg-linkedin-blue rounded-full mx-auto mb-4 flex items-center justify-center">
|
||||
<svg className="w-8 h-8 text-white" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<p className="text-linkedin-gray text-sm">Професійна мережа</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<motion.section
|
||||
{...fadeUpPreset(0.1, 0.8)}
|
||||
className="bg-linkedin-light-gray py-16 lg:py-24"
|
||||
>
|
||||
<div className="section-container">
|
||||
<div className="grid lg:grid-cols-2 gap-12 items-center">
|
||||
<motion.div {...fadeUpPreset(0.2, 1.0)}>
|
||||
<h1 className="text-4xl lg:text-5xl font-light text-linkedin-text mb-6 leading-tight">
|
||||
Ласкаво просимо до професійної спільноти!
|
||||
</h1>
|
||||
<div className="space-y-4">
|
||||
<button className="btn-primary w-full sm:w-auto">
|
||||
Приєднатися зараз
|
||||
</button>
|
||||
<div className="flex items-center gap-4">
|
||||
<span className="text-sm text-linkedin-gray">або</span>
|
||||
<button className="text-linkedin-blue hover:underline font-semibold">
|
||||
Увійти
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-sm text-linkedin-gray mt-6">
|
||||
Умови та додаткові умови конфіденційності застосовуються.
|
||||
</p>
|
||||
<p className="text-sm text-linkedin-gray mt-2">
|
||||
Цей сайт захищений reCAPTCHA та застосовуються Політика конфіденційності та Умови обслуговування Google.
|
||||
</p>
|
||||
<p className="text-sm text-linkedin-gray mt-4">
|
||||
Вперше на LinkedIn? <a href="#" className="text-linkedin-blue hover:underline">Приєднайтеся зараз</a>
|
||||
</p>
|
||||
</motion.div>
|
||||
<motion.div {...fadeUpPreset(0.4, 1.0)} className="relative">
|
||||
<div className="bg-white rounded-lg p-8 shadow-lg">
|
||||
<div className="w-full h-64 bg-gradient-to-br from-blue-100 to-orange-100 rounded-lg flex items-center justify-center">
|
||||
<div className="text-center">
|
||||
<div className="w-16 h-16 bg-linkedin-blue rounded-full mx-auto mb-4 flex items-center justify-center">
|
||||
<svg className="w-8 h-8 text-white" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<p className="text-linkedin-gray text-sm">Професійна мережа</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
</div>
|
||||
</motion.section>
|
||||
);
|
||||
};
|
||||
|
||||
export default Hero;
|
||||
75
src/components/JobSearch.js
Normal file
75
src/components/JobSearch.js
Normal file
@@ -0,0 +1,75 @@
|
||||
import React from 'react';
|
||||
import { motion, useReducedMotion } from 'framer-motion';
|
||||
|
||||
const fadeUpPreset = (delay = 0, duration = 1.2) => ({
|
||||
initial: { opacity: 0, y: 20 },
|
||||
whileInView: { opacity: 1, y: 0 },
|
||||
viewport: { once: true, amount: 0.2 },
|
||||
transition: { delay, duration, ease: "easeOut" }
|
||||
});
|
||||
|
||||
const JobSearch = () => {
|
||||
const shouldReduce = useReducedMotion();
|
||||
|
||||
const jobCategories = [
|
||||
'Інженерія', 'Розробка бізнесу', 'Фінанси',
|
||||
'Адміністративна допомога', 'Роздрібна торгівля', 'Операції в роздрібі',
|
||||
'Служба підтримки', 'Операції', 'Інформаційні технології',
|
||||
'Управління персоналом', 'Маркетинг', 'Юридичні послуги'
|
||||
];
|
||||
|
||||
if (shouldReduce) {
|
||||
return (
|
||||
<section className="py-16 bg-white">
|
||||
<div className="section-container">
|
||||
<div className="max-w-2xl">
|
||||
<h2 className="text-3xl lg:text-4xl font-light text-linkedin-text mb-6">
|
||||
Знайдіть вакансію або стажування, що підходить саме вам
|
||||
</h2>
|
||||
<div className="flex flex-wrap gap-3">
|
||||
{jobCategories.map((category, index) => (
|
||||
<button key={index} className="tag-button">
|
||||
{category}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<motion.section
|
||||
{...fadeUpPreset(0.1, 1.0)}
|
||||
className="py-16 bg-white"
|
||||
>
|
||||
<div className="section-container">
|
||||
<div className="max-w-2xl">
|
||||
<motion.h2
|
||||
{...fadeUpPreset(0.2, 1.0)}
|
||||
className="text-3xl lg:text-4xl font-light text-linkedin-text mb-6"
|
||||
>
|
||||
Знайдіть вакансію або стажування, що підходить саме вам
|
||||
</motion.h2>
|
||||
<motion.div
|
||||
{...fadeUpPreset(0.3, 1.0)}
|
||||
className="flex flex-wrap gap-3"
|
||||
>
|
||||
{jobCategories.map((category, index) => (
|
||||
<motion.button
|
||||
key={index}
|
||||
{...fadeUpPreset(0.4 + index * 0.05, 0.6)}
|
||||
className="tag-button"
|
||||
>
|
||||
{category}
|
||||
</motion.button>
|
||||
))}
|
||||
</motion.div>
|
||||
</div>
|
||||
</div>
|
||||
</motion.section>
|
||||
);
|
||||
};
|
||||
|
||||
export default JobSearch;
|
||||
81
src/components/KeepInTouch.js
Normal file
81
src/components/KeepInTouch.js
Normal file
@@ -0,0 +1,81 @@
|
||||
import React from 'react';
|
||||
import { motion, useReducedMotion } from 'framer-motion';
|
||||
|
||||
const fadeUpPreset = (delay = 0, duration = 1.2) => ({
|
||||
initial: { opacity: 0, y: 20 },
|
||||
whileInView: { opacity: 1, y: 0 },
|
||||
viewport: { once: true, amount: 0.2 },
|
||||
transition: { delay, duration, ease: "easeOut" }
|
||||
});
|
||||
|
||||
const KeepInTouch = () => {
|
||||
const shouldReduce = useReducedMotion();
|
||||
|
||||
const categories = [
|
||||
'Ігри', 'Веб-браузер', 'Бізнес', 'Новини', 'Подкасти', 'Соціальні'
|
||||
];
|
||||
|
||||
if (shouldReduce) {
|
||||
return (
|
||||
<section className="py-16 bg-linkedin-light-gray">
|
||||
<div className="section-container">
|
||||
<div className="max-w-2xl">
|
||||
<h2 className="text-3xl lg:text-4xl font-light text-linkedin-text mb-6">
|
||||
Зберігайте гостроту розуму за допомогою ігор
|
||||
</h2>
|
||||
<p className="text-linkedin-gray mb-8">
|
||||
Щоденні головоломки та ігри допоможуть вам залишатися в тонусі та розвивати когнітивні здібності. Грайте самостійно або змагайтеся з колегами.
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-3 mb-8">
|
||||
{categories.map((category, index) => (
|
||||
<button key={index} className="tag-button">
|
||||
{category}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<motion.section
|
||||
{...fadeUpPreset(0.1, 1.0)}
|
||||
className="py-16 bg-linkedin-light-gray"
|
||||
>
|
||||
<div className="section-container">
|
||||
<div className="max-w-2xl">
|
||||
<motion.h2
|
||||
{...fadeUpPreset(0.2, 1.0)}
|
||||
className="text-3xl lg:text-4xl font-light text-linkedin-text mb-6"
|
||||
>
|
||||
Зберігайте гостроту розуму за допомогою ігор
|
||||
</motion.h2>
|
||||
<motion.p
|
||||
{...fadeUpPreset(0.3, 1.0)}
|
||||
className="text-linkedin-gray mb-8"
|
||||
>
|
||||
Щоденні головоломки та ігри допоможуть вам залишатися в тонусі та розвивати когнітивні здібності. Грайте самостійно або змагайтеся з колегами.
|
||||
</motion.p>
|
||||
<motion.div
|
||||
{...fadeUpPreset(0.4, 1.0)}
|
||||
className="flex flex-wrap gap-3 mb-8"
|
||||
>
|
||||
{categories.map((category, index) => (
|
||||
<motion.button
|
||||
key={index}
|
||||
{...fadeUpPreset(0.5 + index * 0.1, 0.6)}
|
||||
className="tag-button"
|
||||
>
|
||||
{category}
|
||||
</motion.button>
|
||||
))}
|
||||
</motion.div>
|
||||
</div>
|
||||
</div>
|
||||
</motion.section>
|
||||
);
|
||||
};
|
||||
|
||||
export default KeepInTouch;
|
||||
52
src/components/PostJobs.js
Normal file
52
src/components/PostJobs.js
Normal file
@@ -0,0 +1,52 @@
|
||||
import React from 'react';
|
||||
import { motion, useReducedMotion } from 'framer-motion';
|
||||
|
||||
const fadeUpPreset = (delay = 0, duration = 1.2) => ({
|
||||
initial: { opacity: 0, y: 20 },
|
||||
whileInView: { opacity: 1, y: 0 },
|
||||
viewport: { once: true, amount: 0.2 },
|
||||
transition: { delay, duration, ease: "easeOut" }
|
||||
});
|
||||
|
||||
const PostJobs = () => {
|
||||
const shouldReduce = useReducedMotion();
|
||||
|
||||
if (shouldReduce) {
|
||||
return (
|
||||
<section className="py-16 bg-red-50">
|
||||
<div className="section-container text-center">
|
||||
<h2 className="text-3xl lg:text-4xl font-light text-linkedin-text mb-6">
|
||||
Розмістіть вакансію, щоб її побачили мільйони людей
|
||||
</h2>
|
||||
<button className="btn-secondary">
|
||||
Розмістити вакансію
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<motion.section
|
||||
{...fadeUpPreset(0.1, 1.0)}
|
||||
className="py-16 bg-red-50"
|
||||
>
|
||||
<div className="section-container text-center">
|
||||
<motion.h2
|
||||
{...fadeUpPreset(0.2, 1.0)}
|
||||
className="text-3xl lg:text-4xl font-light text-linkedin-text mb-6"
|
||||
>
|
||||
Розмістіть вакансію, щоб її побачили мільйони людей
|
||||
</motion.h2>
|
||||
<motion.button
|
||||
{...fadeUpPreset(0.3, 1.0)}
|
||||
className="btn-secondary"
|
||||
>
|
||||
Розмістити вакансію
|
||||
</motion.button>
|
||||
</div>
|
||||
</motion.section>
|
||||
);
|
||||
};
|
||||
|
||||
export default PostJobs;
|
||||
86
src/components/WhoIsLinkedIn.js
Normal file
86
src/components/WhoIsLinkedIn.js
Normal file
@@ -0,0 +1,86 @@
|
||||
import React from 'react';
|
||||
import { motion, useReducedMotion } from 'framer-motion';
|
||||
|
||||
const fadeUpPreset = (delay = 0, duration = 1.2) => ({
|
||||
initial: { opacity: 0, y: 20 },
|
||||
whileInView: { opacity: 1, y: 0 },
|
||||
viewport: { once: true, amount: 0.2 },
|
||||
transition: { delay, duration, ease: "easeOut" }
|
||||
});
|
||||
|
||||
const WhoIsLinkedIn = () => {
|
||||
const shouldReduce = useReducedMotion();
|
||||
|
||||
const links = [
|
||||
'Знайти колегу чи однокласника',
|
||||
'Знайти нову вакансію',
|
||||
'Знайти курс або навчання'
|
||||
];
|
||||
|
||||
if (shouldReduce) {
|
||||
return (
|
||||
<section className="py-16 bg-white">
|
||||
<div className="section-container">
|
||||
<div className="max-w-2xl">
|
||||
<h2 className="text-3xl lg:text-4xl font-light text-linkedin-text mb-6">
|
||||
Для кого LinkedIn?
|
||||
</h2>
|
||||
<p className="text-linkedin-gray mb-8">
|
||||
Для тих, хто хоче навчатися вдосконалюватися професійно.
|
||||
</p>
|
||||
<div className="space-y-4">
|
||||
{links.map((link, index) => (
|
||||
<div key={index}>
|
||||
<a href="#" className="text-linkedin-blue hover:underline font-medium">
|
||||
{link}
|
||||
</a>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<motion.section
|
||||
{...fadeUpPreset(0.1, 1.0)}
|
||||
className="py-16 bg-white"
|
||||
>
|
||||
<div className="section-container">
|
||||
<div className="max-w-2xl">
|
||||
<motion.h2
|
||||
{...fadeUpPreset(0.2, 1.0)}
|
||||
className="text-3xl lg:text-4xl font-light text-linkedin-text mb-6"
|
||||
>
|
||||
Для кого LinkedIn?
|
||||
</motion.h2>
|
||||
<motion.p
|
||||
{...fadeUpPreset(0.3, 1.0)}
|
||||
className="text-linkedin-gray mb-8"
|
||||
>
|
||||
Для тих, хто хоче навчатися вдосконалюватися професійно.
|
||||
</motion.p>
|
||||
<motion.div
|
||||
{...fadeUpPreset(0.4, 1.0)}
|
||||
className="space-y-4"
|
||||
>
|
||||
{links.map((link, index) => (
|
||||
<motion.div
|
||||
key={index}
|
||||
{...fadeUpPreset(0.5 + index * 0.1, 0.6)}
|
||||
>
|
||||
<a href="#" className="text-linkedin-blue hover:underline font-medium">
|
||||
{link}
|
||||
</a>
|
||||
</motion.div>
|
||||
))}
|
||||
</motion.div>
|
||||
</div>
|
||||
</div>
|
||||
</motion.section>
|
||||
);
|
||||
};
|
||||
|
||||
export default WhoIsLinkedIn;
|
||||
33
src/index.css
Normal file
33
src/index.css
Normal file
@@ -0,0 +1,33 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer base {
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
||||
line-height: 1.5;
|
||||
color: #000000e6;
|
||||
}
|
||||
}
|
||||
|
||||
@layer components {
|
||||
.btn-primary {
|
||||
@apply bg-linkedin-blue hover:bg-linkedin-dark-blue text-white font-semibold py-3 px-6 rounded-full transition-colors duration-200;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
@apply border border-linkedin-blue text-linkedin-blue hover:bg-linkedin-blue hover:text-white font-semibold py-3 px-6 rounded-full transition-colors duration-200;
|
||||
}
|
||||
|
||||
.section-container {
|
||||
@apply max-w-6xl mx-auto px-4 sm:px-6 lg:px-8;
|
||||
}
|
||||
|
||||
.tag-button {
|
||||
@apply inline-block bg-white border border-linkedin-border text-linkedin-gray px-4 py-2 rounded-full text-sm hover:bg-gray-50 transition-colors duration-200;
|
||||
}
|
||||
}
|
||||
13
src/index.js
Normal file
13
src/index.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import React from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import './index.css';
|
||||
import App from './App';
|
||||
|
||||
const container = document.getElementById('root');
|
||||
const root = createRoot(container);
|
||||
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>
|
||||
);
|
||||
27
tailwind.config.js
Normal file
27
tailwind.config.js
Normal file
@@ -0,0 +1,27 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: [
|
||||
"./src/**/*.{js,jsx,ts,tsx}",
|
||||
],
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
'linkedin-blue': '#0a66c2',
|
||||
'linkedin-dark-blue': '#004182',
|
||||
'linkedin-light-blue': '#378fe9',
|
||||
'linkedin-gray': '#666666',
|
||||
'linkedin-light-gray': '#f3f2ef',
|
||||
'linkedin-border': '#e6e6e6',
|
||||
'linkedin-text': '#000000e6'
|
||||
},
|
||||
fontFamily: {
|
||||
'sans': ['-apple-system', 'BlinkMacSystemFont', 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'sans-serif']
|
||||
},
|
||||
spacing: {
|
||||
'18': '4.5rem',
|
||||
'88': '22rem'
|
||||
}
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
}
|
||||
5
vercel.json
Normal file
5
vercel.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"installCommand": "npm install",
|
||||
"buildCommand": "CI=false npm run build",
|
||||
"outputDirectory": "build"
|
||||
}
|
||||
Reference in New Issue
Block a user