LocalPro Finder v2 — без AI-диагностики, Coming Soon окно

This commit is contained in:
2026-07-03 20:32:31 +00:00
commit c529273c38
17 changed files with 1305 additions and 0 deletions
+41
View File
@@ -0,0 +1,41 @@
{
"name": "freelancer-match-frontend",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"@hookform/resolvers": "^3.9.0",
"@radix-ui/react-dialog": "^1.1.2",
"@radix-ui/react-dropdown-menu": "^2.1.2",
"@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-select": "^2.1.2",
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-tabs": "^1.1.1",
"@tanstack/react-query": "^5.60.5",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"lucide-react": "^0.460.0",
"next": "^14.2.0",
"react": "^18.3.0",
"react-dom": "^18.3.0",
"react-hook-form": "^7.53.2",
"tailwind-merge": "^2.6.0",
"zod": "^3.23.8",
"zustand": "^4.5.5"
},
"devDependencies": {
"@types/node": "^20.17.0",
"@types/react": "^18.3.0",
"@types/react-dom": "^18.3.0",
"autoprefixer": "^10.4.20",
"eslint": "^8.57.0",
"postcss": "^8.4.49",
"tailwindcss": "^3.4.15",
"typescript": "^5.6.0"
}
}
+109
View File
@@ -0,0 +1,109 @@
import { useState } from "react";
import { Search, MapPin, Star, MessageCircle, ShieldCheck, Clock, ChevronRight } from "lucide-react";
export default function Home() {
const [searchQuery, setSearchQuery] = useState("");
const [location, setLocation] = useState("");
return (
<div className="min-h-screen bg-gradient-to-b from-blue-50 to-white">
{/* Hero */}
<section className="relative overflow-hidden bg-gradient-to-r from-blue-600 to-indigo-700 text-white py-24 px-8">
<div className="max-w-4xl mx-auto text-center">
<h1 className="text-5xl font-bold mb-4">LocalPro Finder</h1>
<p className="text-xl opacity-90 mb-8">Найдите проверенных мастеров рядом с вами</p>
{/* Search */}
<div className="flex gap-3 max-w-2xl mx-auto">
<input
type="text"
placeholder="Что вам нужно?"
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className="flex-1 px-4 py-3 rounded-lg text-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-300"
/>
<button className="px-6 py-3 bg-white text-blue-700 font-semibold rounded-lg hover:bg-blue-50 transition">
Найти
</button>
</div>
{/* Location */}
<div className="flex items-center justify-center gap-2 mt-4 text-sm opacity-80">
<MapPin size={16} />
<input
type="text"
placeholder="Ваш город или адрес"
value={location}
onChange={(e) => setLocation(e.target.value)}
className="bg-transparent border-none outline-none text-white placeholder-blue-200 w-full max-w-xs"
/>
</div>
</div>
</section>
{/* Categories */}
<section className="py-16 px-8">
<h2 className="text-3xl font-bold text-center mb-12">Категории мастеров</h2>
<div className="grid grid-cols-2 md:grid-cols-4 gap-6 max-w-5xl mx-auto">
{[
{ icon: "🔧", name: "Сантехника" },
{ icon: "⚡", name: "Электрика" },
{ icon: "🏠", name: "Ремонт" },
{ icon: "🎨", name: "Дизайн" },
{ icon: "🌿", name: "Ландшафт" },
{ icon: "🔑", name: "Замок." },
].map((cat) => (
<div key={cat.name} className="bg-white rounded-xl p-6 shadow-sm hover:shadow-md transition cursor-pointer text-center">
<span className="text-4xl">{cat.icon}</span>
<p className="mt-3 font-medium">{cat.name}</p>
</div>
))}
</div>
</section>
{/* AI Diagnosis — Coming Soon */}
<section className="py-16 px-8 bg-indigo-50">
<div className="max-w-4xl mx-auto text-center">
<ShieldCheck size={48} className="mx-auto mb-4 text-indigo-600" />
<h2 className="text-3xl font-bold mb-2">AI Диагностика</h2>
<p className="text-lg opacity-75 mb-6">Умная диагностика проблемы скоро!</p>
<div className="inline-block bg-white rounded-xl p-8 shadow-sm border border-indigo-100 max-w-md">
<div className="flex items-center gap-3 mb-4">
<Clock size={20} className="text-indigo-500" />
<span className="font-semibold text-indigo-700">Coming Soon</span>
</div>
<p className="text-sm opacity-60">
AI задаст вопросы о вашей проблеме и поможет мастеру точнее оценить стоимость работ.
Функция в разработке следите за обновлениями!
</p>
</div>
</div>
</section>
{/* How it works */}
<section className="py-16 px-8">
<h2 className="text-3xl font-bold text-center mb-12">Как это работает</h2>
<div className="grid md:grid-cols-4 gap-8 max-w-5xl mx-auto">
{[
{ step: "1", title: "Опишите задачу", desc: "Расскажите что нужно сделать" },
{ step: "2", title: "Найдите мастера", desc: "Сравните отзывы и цены" },
{ step: "3", title: "Обсудите детали", desc: "Чат с мастером в приложении" },
{ step: "4", title: "Оплатите безопасно", desc: "Escrow-гарант сделки" },
].map((item) => (
<div key={item.step} className="text-center">
<div className="w-12 h-12 rounded-full bg-blue-600 text-white flex items-center justify-center mx-auto mb-4 font-bold">{item.step}</div>
<h3 className="font-semibold mb-2">{item.title}</h3>
<p className="text-sm opacity-75">{item.desc}</p>
</div>
))}
</div>
</section>
{/* Footer */}
<footer className="py-8 text-center text-sm opacity-60">
© 2026 LocalPro Finder. Все права защищены.
</footer>
</div>
);
}
+49
View File
@@ -0,0 +1,49 @@
import { useState } from "react";
import { Mail, Lock, Eye, EyeOff } from "lucide-react";
export default function Login() {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [showPassword, setShowPassword] = useState(false);
return (
<div className="min-h-screen bg-gradient-to-b from-blue-50 to-white flex items-center justify-center px-4">
<div className="bg-white rounded-xl shadow-lg p-8 w-full max-w-md">
<h1 className="text-2xl font-bold text-center mb-6">Вход в LocalPro Finder</h1>
<div className="space-y-4">
<div>
<label className="block text-sm font-medium mb-1">Email</label>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="your@email.com"
className="w-full px-4 py-3 rounded-lg border focus:outline-none focus:ring-2 focus:ring-blue-300"
/>
</div>
<div>
<label className="block text-sm font-medium mb-1">Пароль</label>
<input
type={showPassword ? "text" : "password"}
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="••••••••"
className="w-full px-4 py-3 rounded-lg border focus:outline-none focus:ring-2 focus:ring-blue-300"
/>
</div>
<button className="w-full py-3 bg-blue-600 text-white font-semibold rounded-lg hover:bg-blue-700 transition">
Войти
</button>
<p className="text-center text-sm opacity-60">
Нет аккаунта?{" "}
<a href="/register" className="text-blue-600 hover:underline">Зарегистрироваться</a>
</p>
</div>
</div>
</div>
);
}
+35
View File
@@ -0,0 +1,35 @@
import { useState } from "react";
import { Mail, Lock, User, Phone } from "lucide-react";
export default function Register() {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [firstName, setFirstName] = useState("");
const [lastName, setLastName] = useState("");
const [phone, setPhone] = useState("");
return (
<div className="min-h-screen bg-gradient-to-b from-blue-50 to-white flex items-center justify-center px-4 py-12">
<div className="bg-white rounded-xl shadow-lg p-8 w-full max-w-md">
<h1 className="text-2xl font-bold text-center mb-6">Регистрация</h1>
<div className="space-y-4">
<input value={firstName} onChange={(e) => setFirstName(e.target.value)} placeholder="Имя" className="w-full px-4 py-3 rounded-lg border focus:outline-none focus:ring-2 focus:ring-blue-300" />
<input value={lastName} onChange={(e) => setLastName(e.target.value)} placeholder="Фамилия" className="w-full px-4 py-3 rounded-lg border focus:outline-none focus:ring-2 focus:ring-blue-300" />
<input type="email" value={email} onChange={(e) => setEmail(e.target.value)} placeholder="Email" className="w-full px-4 py-3 rounded-lg border focus:outline-none focus:ring-2 focus:ring-blue-300" />
<input type="password" value={password} onChange={(e) => setPassword(e.target.value)} placeholder="Пароль" className="w-full px-4 py-3 rounded-lg border focus:outline-none focus:ring-2 focus:ring-blue-300" />
<input type="tel" value={phone} onChange={(e) => setPhone(e.target.value)} placeholder="Телефон (необязательно)" className="w-full px-4 py-3 rounded-lg border focus:outline-none focus:ring-2 focus:ring-blue-300" />
<button className="w-full py-3 bg-blue-600 text-white font-semibold rounded-lg hover:bg-blue-700 transition">
Создать аккаунт
</button>
<p className="text-center text-sm opacity-60">
Уже есть аккаунт?{" "}
<a href="/login" className="text-blue-600 hover:underline">Войти</a>
</p>
</div>
</div>
</div>
);
}