added lockli screen
All checks were successful
Build & Deploy Vite App (Docker Compose) / build-and-deploy (push) Successful in 41s
All checks were successful
Build & Deploy Vite App (Docker Compose) / build-and-deploy (push) Successful in 41s
This commit is contained in:
12
src/App.jsx
12
src/App.jsx
@@ -2,10 +2,11 @@ import React from 'react';
|
|||||||
import { BrowserRouter as Router, Routes, Route, useLocation } from 'react-router-dom';
|
import { BrowserRouter as Router, Routes, Route, useLocation } from 'react-router-dom';
|
||||||
import Home from './pages/Home';
|
import Home from './pages/Home';
|
||||||
import Portal from './pages/Portal';
|
import Portal from './pages/Portal';
|
||||||
import LockliPrivacy from './pages/LockliPrivacy'; // <-- YENİ EKLENDİ
|
import LockliPrivacy from './pages/LockliPrivacy';
|
||||||
|
import PasswordManagerDetail from './pages/PasswordManagerDetail';
|
||||||
|
|
||||||
import { AnimatePresence } from 'framer-motion';
|
import { AnimatePresence } from 'framer-motion';
|
||||||
|
|
||||||
// Animasyonlu geçişler için bir Wrapper bileşeni
|
|
||||||
function AnimatedRoutes() {
|
function AnimatedRoutes() {
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
|
|
||||||
@@ -14,9 +15,10 @@ function AnimatedRoutes() {
|
|||||||
<Routes location={location} key={location.pathname}>
|
<Routes location={location} key={location.pathname}>
|
||||||
<Route path="/" element={<Home />} />
|
<Route path="/" element={<Home />} />
|
||||||
<Route path="/portal" element={<Portal />} />
|
<Route path="/portal" element={<Portal />} />
|
||||||
|
|
||||||
{/* Lockli Privacy Policy – yalnızca URL'den erişilecek */}
|
|
||||||
<Route path="/lockli/privacy" element={<LockliPrivacy />} />
|
<Route path="/lockli/privacy" element={<LockliPrivacy />} />
|
||||||
|
|
||||||
|
<Route path="/projects/lockli" element={<PasswordManagerDetail />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</AnimatePresence>
|
</AnimatePresence>
|
||||||
);
|
);
|
||||||
@@ -30,4 +32,4 @@ function App() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
@@ -3,11 +3,10 @@ import { motion, AnimatePresence } from 'framer-motion';
|
|||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import {
|
import {
|
||||||
Terminal, Globe, Shield, Database,
|
Terminal, Globe, Shield, Database,
|
||||||
Github, Twitter, Linkedin, Mail, Lock, X, ChevronRight, ExternalLink,
|
Mail, Lock, X, ChevronRight, ExternalLink, Github, Linkedin,
|
||||||
Coffee, Zap, Smartphone, Layers, Box, Server, Loader2 // Loader2 eklendi
|
Coffee, Zap, Smartphone, Layers, Box, Server, Loader2
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
|
|
||||||
// --- YETENEKLER ---
|
|
||||||
const skills = [
|
const skills = [
|
||||||
{ name: "Java", icon: <Coffee size={20} />, desc: "Core & Enterprise" },
|
{ name: "Java", icon: <Coffee size={20} />, desc: "Core & Enterprise" },
|
||||||
{ name: "Spring Boot", icon: <Zap size={20} />, desc: "Microservices" },
|
{ name: "Spring Boot", icon: <Zap size={20} />, desc: "Microservices" },
|
||||||
@@ -27,10 +26,10 @@ const projects = [
|
|||||||
link: "#"
|
link: "#"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Mobil Sosyal Medya Uygulaması",
|
title: "Mobil Offline Parola Yöneticisi",
|
||||||
desc: "Flutter kullanılarak geliştirilen, hem iOS hem Android uyumlu modern arayüzlü sosyal medya uygulaması.",
|
desc: "Flutter kullanılarak geliştirilen, hem iOS hem Android uyumlu modern arayüzlü tamamen local parola yöneticisi.",
|
||||||
tags: ["Flutter", "Dart", "Rest API"],
|
tags: ["Flutter", "Dart", "HiveDB"],
|
||||||
link: "#"
|
link: "/projects/lockli"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Linux Tabanlı Sunucu Altyapısı",
|
title: "Linux Tabanlı Sunucu Altyapısı",
|
||||||
@@ -45,7 +44,6 @@ export default function Home() {
|
|||||||
const [username, setUsername] = useState("");
|
const [username, setUsername] = useState("");
|
||||||
const [password, setPassword] = useState("");
|
const [password, setPassword] = useState("");
|
||||||
|
|
||||||
// Yeni State'ler
|
|
||||||
const [error, setError] = useState("");
|
const [error, setError] = useState("");
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
@@ -73,13 +71,10 @@ export default function Home() {
|
|||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
// Başarılı giriş: Token'ı sakla
|
|
||||||
// Backend'den { token: "..." } veya { accessToken: "..." } döndüğünü varsayıyoruz.
|
|
||||||
sessionStorage.setItem('authToken', data.token || data.accessToken);
|
sessionStorage.setItem('authToken', data.token || data.accessToken);
|
||||||
sessionStorage.setItem('user', JSON.stringify(data.user)); // Opsiyonel: Kullanıcı bilgisini sakla
|
sessionStorage.setItem('user', JSON.stringify(data.user));
|
||||||
navigate('/portal');
|
navigate('/portal');
|
||||||
} else {
|
} else {
|
||||||
// Backend'den gelen hata mesajını göster
|
|
||||||
setError(data.message || "Giriş başarısız. Bilgileri kontrol edin.");
|
setError(data.message || "Giriş başarısız. Bilgileri kontrol edin.");
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -190,7 +185,6 @@ export default function Home() {
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* --- PROJELER --- */}
|
|
||||||
<section id="projects" className="py-20 px-6 bg-slate-900/50">
|
<section id="projects" className="py-20 px-6 bg-slate-900/50">
|
||||||
<div className="max-w-6xl mx-auto">
|
<div className="max-w-6xl mx-auto">
|
||||||
<h2 className="text-3xl font-bold text-white mb-12 flex items-center gap-3">
|
<h2 className="text-3xl font-bold text-white mb-12 flex items-center gap-3">
|
||||||
@@ -198,7 +192,14 @@ export default function Home() {
|
|||||||
</h2>
|
</h2>
|
||||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||||
{projects.map((project, index) => (
|
{projects.map((project, index) => (
|
||||||
<div key={index} className="glass-panel p-6 rounded-2xl hover:-translate-y-1 transition-transform duration-300 flex flex-col h-full">
|
<div key={index} onClick={() => {
|
||||||
|
if (project.link.startsWith('/')) {
|
||||||
|
navigate(project.link);
|
||||||
|
}
|
||||||
|
else if (project.link !== '#') {
|
||||||
|
window.open(project.link, '_blank');
|
||||||
|
}
|
||||||
|
}} className="glass-panel p-6 rounded-2xl hover:-translate-y-1 transition-transform duration-300 flex flex-col h-full cursor-pointer group">
|
||||||
<h3 className="text-xl font-bold text-white mb-3">{project.title}</h3>
|
<h3 className="text-xl font-bold text-white mb-3">{project.title}</h3>
|
||||||
<p className="text-slate-400 mb-6 text-sm leading-relaxed flex-grow">{project.desc}</p>
|
<p className="text-slate-400 mb-6 text-sm leading-relaxed flex-grow">{project.desc}</p>
|
||||||
<div className="flex flex-wrap gap-2 mb-6">
|
<div className="flex flex-wrap gap-2 mb-6">
|
||||||
@@ -208,16 +209,15 @@ export default function Home() {
|
|||||||
</span>
|
</span>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<a href={project.link} className="inline-flex items-center text-sm font-semibold text-white hover:text-orange-400 transition-colors mt-auto">
|
<div className="inline-flex items-center text-sm font-semibold text-white group-hover:text-orange-400 transition-colors mt-auto">
|
||||||
İncele <ExternalLink size={14} className="ml-2" />
|
İncele <ExternalLink size={14} className="ml-2" />
|
||||||
</a>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* --- İLETİŞİM --- */}
|
|
||||||
<section id="contact" className="py-20 px-6 text-center">
|
<section id="contact" className="py-20 px-6 text-center">
|
||||||
<div className="max-w-2xl mx-auto">
|
<div className="max-w-2xl mx-auto">
|
||||||
<h2 className="text-3xl font-bold text-white mb-6">İletişime Geç</h2>
|
<h2 className="text-3xl font-bold text-white mb-6">İletişime Geç</h2>
|
||||||
@@ -240,7 +240,6 @@ export default function Home() {
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* --- LOGİN MODAL --- */}
|
|
||||||
<AnimatePresence>
|
<AnimatePresence>
|
||||||
{isModalOpen && (
|
{isModalOpen && (
|
||||||
<div className="fixed inset-0 z-[100] flex items-center justify-center p-4">
|
<div className="fixed inset-0 z-[100] flex items-center justify-center p-4">
|
||||||
|
|||||||
155
src/pages/PasswordManagerDetail.jsx
Normal file
155
src/pages/PasswordManagerDetail.jsx
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { motion } from 'framer-motion';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
import {
|
||||||
|
ArrowLeft, Shield, Smartphone, Lock,
|
||||||
|
WifiOff, Database, Apple, Play, CheckCircle
|
||||||
|
} from 'lucide-react';
|
||||||
|
|
||||||
|
export default function PasswordManagerDetail() {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
// Özellik listesi
|
||||||
|
const features = [
|
||||||
|
"AES-256 Bit Şifreleme",
|
||||||
|
"İnternet İzni Gerektirmez (Tamamen Offline)",
|
||||||
|
"Biyometrik Giriş (FaceID / TouchID)",
|
||||||
|
"Otomatik Parola Oluşturucu",
|
||||||
|
"Kategorize Edilmiş Kayıtlar",
|
||||||
|
"Yedekleme ve Geri Yükleme (Şifreli)"
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="bg-slate-900 min-h-screen text-slate-200 selection:bg-orange-500 selection:text-white pb-20">
|
||||||
|
|
||||||
|
{/* --- NAVBAR / GERİ DÖN --- */}
|
||||||
|
<nav className="fixed top-0 left-0 right-0 z-50 glass-panel border-b border-white/10 px-6 py-4">
|
||||||
|
<div className="max-w-6xl mx-auto flex items-center">
|
||||||
|
<button
|
||||||
|
onClick={() => navigate(-1)}
|
||||||
|
className="flex items-center gap-2 text-slate-400 hover:text-white transition-colors"
|
||||||
|
>
|
||||||
|
<ArrowLeft size={20} />
|
||||||
|
<span className="font-medium">Ana Sayfaya Dön</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
{/* --- İÇERİK --- */}
|
||||||
|
<div className="max-w-6xl mx-auto px-6 pt-32">
|
||||||
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||||
|
|
||||||
|
{/* --- SOL TARAFTAKİ GÖRSEL ALANI --- */}
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, x: -50 }}
|
||||||
|
animate={{ opacity: 1, x: 0 }}
|
||||||
|
transition={{ duration: 0.6 }}
|
||||||
|
className="flex flex-col items-center"
|
||||||
|
>
|
||||||
|
{/* Logo ve Başlık (Mobil Görünüm için) */}
|
||||||
|
<div className="flex items-center gap-4 mb-8 lg:hidden">
|
||||||
|
<div className="p-4 bg-orange-500/10 rounded-2xl border border-orange-500/20">
|
||||||
|
<Shield size={40} className="text-orange-500" />
|
||||||
|
</div>
|
||||||
|
<h1 className="text-2xl font-bold text-white">Mobil Offline<br/>Parola Yöneticisi</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Telefon Mockup'ı */}
|
||||||
|
<div className="relative w-[280px] h-[580px] bg-slate-800 rounded-[3rem] border-8 border-slate-700 shadow-2xl shadow-orange-500/10 flex items-center justify-center overflow-hidden">
|
||||||
|
{/* Ekran İçi Temsili Görsel */}
|
||||||
|
<div className="absolute inset-0 bg-slate-900 flex flex-col items-center justify-center p-6 text-center">
|
||||||
|
<Lock size={64} className="text-orange-500 mb-4 opacity-50" />
|
||||||
|
<h3 className="text-xl font-bold text-white mb-2">Güvenli Kasa</h3>
|
||||||
|
<p className="text-xs text-slate-500">Tüm verileriniz cihazınızda şifreli olarak saklanır.</p>
|
||||||
|
|
||||||
|
<div className="w-full mt-8 space-y-3">
|
||||||
|
<div className="h-12 bg-slate-800 rounded-lg w-full animate-pulse"></div>
|
||||||
|
<div className="h-12 bg-slate-800 rounded-lg w-full animate-pulse delay-75"></div>
|
||||||
|
<div className="h-12 bg-slate-800 rounded-lg w-full animate-pulse delay-150"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Kamera Çentiği */}
|
||||||
|
<div className="absolute top-0 w-32 h-6 bg-slate-700 rounded-b-xl z-10"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Alt Bilgi Kartları */}
|
||||||
|
<div className="flex gap-4 mt-8">
|
||||||
|
<div className="bg-slate-800/50 p-3 rounded-lg border border-white/5 text-center w-24">
|
||||||
|
<Smartphone className="mx-auto mb-2 text-blue-400" size={20} />
|
||||||
|
<span className="text-xs text-slate-400">iOS & Android</span>
|
||||||
|
</div>
|
||||||
|
<div className="bg-slate-800/50 p-3 rounded-lg border border-white/5 text-center w-24">
|
||||||
|
<WifiOff className="mx-auto mb-2 text-red-400" size={20} />
|
||||||
|
<span className="text-xs text-slate-400">%100 Offline</span>
|
||||||
|
</div>
|
||||||
|
<div className="bg-slate-800/50 p-3 rounded-lg border border-white/5 text-center w-24">
|
||||||
|
<Database className="mx-auto mb-2 text-green-400" size={20} />
|
||||||
|
<span className="text-xs text-slate-400">Hive DB</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
{/* --- SAĞ TARAFTAKİ DETAYLAR --- */}
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, x: 50 }}
|
||||||
|
animate={{ opacity: 1, x: 0 }}
|
||||||
|
transition={{ duration: 0.6, delay: 0.2 }}
|
||||||
|
>
|
||||||
|
{/* Logo ve Başlık (Desktop) */}
|
||||||
|
<div className="hidden lg:flex items-center gap-6 mb-8">
|
||||||
|
<div className="p-5 bg-gradient-to-br from-orange-500/20 to-red-500/20 rounded-3xl border border-orange-500/30 shadow-lg shadow-orange-500/10">
|
||||||
|
<Shield size={48} className="text-orange-500" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h1 className="text-4xl font-bold text-white mb-2">Mobil Offline Parola Yöneticisi</h1>
|
||||||
|
<span className="px-3 py-1 bg-white/5 rounded-full text-xs text-slate-400 border border-white/10">v1.2.0 Stable</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 className="text-xl font-semibold text-white mb-4">Proje Hakkında</h2>
|
||||||
|
<p className="text-slate-400 leading-relaxed mb-8 text-lg">
|
||||||
|
Günümüzdeki bulut tabanlı parola yöneticilerinin güvenlik risklerine karşı geliştirilmiş, tamamen yerel çalışan bir mobil uygulamadır.
|
||||||
|
Hiçbir veriniz sunucuya gönderilmez. Flutter ile geliştirilen uygulama, Hive veritabanı kullanarak verileri cihazınızın belleğinde
|
||||||
|
şifreli (AES-256) olarak saklar.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 className="text-xl font-semibold text-white mb-4">Öne Çıkan Özellikler</h2>
|
||||||
|
<ul className="grid grid-cols-1 md:grid-cols-2 gap-3 mb-10">
|
||||||
|
{features.map((item, index) => (
|
||||||
|
<li key={index} className="flex items-start gap-2 text-slate-300 text-sm">
|
||||||
|
<CheckCircle size={18} className="text-orange-500 shrink-0 mt-0.5" />
|
||||||
|
{item}
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div className="border-t border-white/10 pt-8">
|
||||||
|
<h3 className="text-sm font-semibold text-slate-400 uppercase tracking-wider mb-4">Şimdi İndirin</h3>
|
||||||
|
<div className="flex flex-wrap gap-4">
|
||||||
|
{/* App Store Butonu */}
|
||||||
|
<button className="flex items-center gap-3 bg-white text-black px-6 py-3 rounded-xl hover:bg-slate-200 transition-colors">
|
||||||
|
<Apple size={28} fill="currentColor" />
|
||||||
|
<div className="text-left">
|
||||||
|
<div className="text-[10px] font-medium leading-none mb-1">Download on the</div>
|
||||||
|
<div className="text-lg font-bold leading-none">App Store</div>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{/* Google Play Butonu */}
|
||||||
|
<button className="flex items-center gap-3 bg-transparent border border-white/20 text-white px-6 py-3 rounded-xl hover:bg-white/5 transition-colors">
|
||||||
|
<Play size={26} fill="currentColor" />
|
||||||
|
<div className="text-left">
|
||||||
|
<div className="text-[10px] font-medium leading-none mb-1 uppercase">Get it on</div>
|
||||||
|
<div className="text-lg font-bold leading-none">Google Play</div>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</motion.div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user