first commit

This commit is contained in:
cifobandung771-spec 2026-05-27 14:24:52 +07:00
parent a9c0e72a13
commit 22cf466e1d
9 changed files with 394 additions and 5 deletions

View File

@ -1,3 +1,15 @@
import { type RouteConfig, index } from "@react-router/dev/routes";
import { type RouteConfig, index, route } from "@react-router/dev/routes";
export default [index("routes/home.tsx")] satisfies RouteConfig;
export default [
index("routes/home.tsx"),
route("/about", "./routes/about.tsx"),
route("/kontak", "./routes/kontak.tsx"),
route("/register", "./routes/register.tsx"),
route("/portofolio","./routes/portofolio.tsx"),
route("/login","./routes/login.tsx"),
route("/dashboard","./routes/dashboard.tsx"),
] satisfies RouteConfig;

69
app/routes/about.tsx Normal file
View File

@ -0,0 +1,69 @@
export default function About() {
return (
<>
<style>{`
body {
margin: 0;
font-family: 'Poppins', sans-serif;
background: linear-gradient(120deg, #e0e0e0, #bdbdbd, #9e9e9e);
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
.container {
width: 360px;
padding: 30px;
background: linear-gradient(145deg, #ffffff, #d6d6d6);
border-radius: 30px;
box-shadow: 10px 10px 25px rgba(0,0,0,0.2),
-10px -10px 25px rgba(255,255,255,0.6);
text-align: center;
}
h1 {
color: #2f2f2f;
margin-bottom: 5px;
letter-spacing: 2px;
}
h3 {
color: #666;
font-weight: normal;
margin-bottom: 25px;
font-size: 14px;
}
.box {
background: linear-gradient(135deg, #f5f5f5, #cfcfcf);
padding: 18px;
border-radius: 20px;
text-align: left;
line-height: 1.7;
color: #333;
font-size: 14px;
transition: 0.3s;
}
.box:hover {
transform: translateY(-5px);
background: linear-gradient(135deg, #e0e0e0, #b5b5b5);
}
`}</style>
<div className="container">
<h1>ABOUT</h1>
<h3>tentang sayaa</h3>
<div className="box">
saya zahro,saya bisa di panggil zar <br/>
saya memiliki hobi menggambar,dan menyanyi <br/>
saya berusia 17 tahun <br/>
saya sekolah di SMK GUNA CIPTA <br/>
saya mengambil jurusan (RPL) atau Rekayasa Perangkat Lunak
</div>
</div>
</>
);
}

55
app/routes/dashboard.tsx Normal file
View File

@ -0,0 +1,55 @@
import { useNavigate } from "react-router";
import { useState } from "react";
export default function Dashboard() {
const navigate = useNavigate();
const [menu, setMenu] = useState("dashboard");
const menus = ["dashboard", "profile", "settings", "about"];
return (
<div className="flex min-h-screen bg-gray-900 text-white">
{/* SIDEBAR */}
<div className="w-52 bg-gray-800 p-4 flex flex-col justify-between">
<div>
<h1 className="text-xl font-bold mb-6">MyApp</h1>
{menus.map((item) => (
<div
key={item}
onClick={() => setMenu(item)}
className={`p-2 mb-2 rounded cursor-pointer capitalize ${
menu === item ? "bg-purple-600" : "hover:bg-gray-700"
}`}
>
{item}
</div>
))}
</div>
<button
onClick={() => navigate("/login")}
className="bg-red-500 py-1 rounded"
>
Logout
</button>
</div>
{/* CONTENT */}
<div className="flex-1 flex items-center justify-center">
<div className="bg-gray-800 p-10 rounded-xl shadow-lg text-center w-[450px] h-[220px]">
<h1 className="text-2xl font-bold capitalize mb-3">
{menu}
</h1>
<p className="text-gray-400">
Selamat datang di halaman {menu} 👋
</p>
</div>
</div>
</div>
);
}

54
app/routes/kontak.tsx Normal file
View File

@ -0,0 +1,54 @@
export default function Kontak() {
return(
<>
<style>{`
body {
margin: 0;
font-family: 'Poppins', sans-serif;
background: linear-gradient(135deg, #e0e0e0, #bfbfbf);
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
div {
background: linear-gradient(145deg, #ffffff, #d9d9d9);
padding: 30px;
border-radius: 25px;
box-shadow: 0 10px 25px rgba(0,0,0,0.2);
width: 350px;
text-align: center;
}
h1 {
color: #333;
margin-bottom: 20px;
letter-spacing: 1px;
}
p {
background: #f2f2f2;
margin: 10px 0;
padding: 10px;
border-radius: 12px;
color: #444;
font-size: 14px;
transition: 0.3s;
}
p:hover {
background: #d6d6d6;
transform: scale(1.03);
}
`}</style>
<div>
<h1>kontak saya</h1>
<p>no saya = 0895707255300</p>
<p>email saya = zahrotusyita@gmail.com</p>
<p>alamat = Babakannanjung</p>
</div>
</>
)
}

88
app/routes/login.tsx Normal file
View File

@ -0,0 +1,88 @@
import { useState } from "react";
import { useNavigate } from "react-router";
export default function Login() {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const navigate = useNavigate();
const handleLogin = async (e: any) => {
e.preventDefault();
try {
const res = await fetch("http://localhost:3000/login", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
username: email,
password: password
})
});
const data = await res.json();
if (data.success) {
localStorage.setItem("token", data.token);
navigate("/dashboard");
} else {
alert(data.message);
}
} catch (error) {
alert("Server error");
}
};
return (
<div className="min-h-screen bg-gray-500 flex items-center justify-center px-4">
<div className="w-full max-w-sm bg-gray-800 text-white p-6 rounded-xl shadow-lg">
<form onSubmit={handleLogin} className="space-y-4">
<h1 className="text-center text-xl font-bold">
LOGIN
</h1>
<p className="text-center text-sm text-gray-300">
baru di situs ini?{" "}
<span className="text-blue-400 cursor-pointer">
DAFTAR sekarang
</span>
</p>
<input
type="text"
placeholder="e-mail pengguna"
value={email}
onChange={(e) => setEmail(e.target.value)}
className="w-full px-4 py-2 rounded-lg bg-gray-700 text-white placeholder-gray-400 focus:outline-none"
/>
<input
type="password"
placeholder="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
className="w-full px-4 py-2 rounded-lg bg-gray-700 text-white placeholder-gray-400 focus:outline-none"
/>
<div className="flex items-center gap-2 text-sm">
<input type="checkbox" />
<label>I'm not an animal</label>
</div>
<button
type="submit"
className="w-full bg-gray-400 text-white py-2 rounded-lg hover:bg-gray-500 transition"
>
login
</button>
</form>
</div>
</div>
);
}

48
app/routes/portofolio.tsx Normal file
View File

@ -0,0 +1,48 @@
export default function portofolio() {
return(
<div className="min-h-screen flex items-center justify-center bg-gradient-to-br from-gray-200 via-gray-300 to-gray-400 font-sans">
<div className="bg-white/80 backdrop-blur-md shadow-xl rounded-3xl p-8 w-[380px] text-center">
<h1 className="text-2xl font-bold text-gray-800 mb-4 tracking-wide">
portofolio
</h1>
<p className="bg-gray-100 rounded-xl p-2 my-1 text-gray-700 hover:bg-gray-200 transition">
saya adalah pribadi yang ingin belajar dan berkembang
</p>
<p className="bg-gray-100 rounded-xl p-2 my-1 text-gray-700 hover:bg-gray-200 transition">
saya senang mencoba hal-hal baru
</p>
<p className="bg-gray-100 rounded-xl p-2 my-1 text-gray-700 hover:bg-gray-200 transition">
memiliki tanggung jawab yang tinggi
</p>
<p className="bg-gray-100 rounded-xl p-2 my-1 text-gray-700 hover:bg-gray-200 transition">
bagi saya,setiap pengalaman adalah kesempatan untuk terus menjadi versi yang lebih baik
</p>
<p className="mt-4 font-semibold text-gray-800">
ini hasil saya
</p>
<p className="mt-3 font-medium text-gray-700">
kontak yang bisa kalian hubungi
</p>
<div className="flex flex-col gap-2 mt-2">
<a href="mail: zahrotusyita@gmail.com" className="text-blue-500 hover:underline">
gmail:zahrotusyita@gmail.com
</a>
<a href="no:0895707255300" className="text-blue-500 hover:underline">
no: 0895707255300
</a>
</div>
</div>
</div>
)
}

63
app/routes/register.tsx Normal file
View File

@ -0,0 +1,63 @@
export default function Register() {
return (
<div className="min-h-screen bg-gray-500 flex items-center justify-center px-4">
<div className="w-full max-w-sm bg-gray-800 p-6 rounded-lg shadow-lg">
<h1 className="mb-2 text-center text-white text-2xl font-bold">
REGISTER
</h1>
<h2 className="mb-5 text-center text-gray-300 text-sm">
ISI DATA ANDA
</h2>
<form className="space-y-4">
<input
type="email"
placeholder="e-mail pengguna"
className="w-full p-3 rounded-lg bg-gray-700 text-white"
/>
<input
type="text"
placeholder="nama pengguna"
className="w-full p-3 rounded-lg bg-gray-700 text-white"
/>
<input
type="password"
placeholder="password"
className="w-full p-3 rounded-lg bg-gray-700 text-white"
/>
{/* ✅ CHECKBOX SETUJU */}
<div className="text-white text-sm">
<label className="flex items-center gap-2">
<input type="checkbox" className="w-4 h-4" />
konfir password
</label>
</div>
{/* ✅ CHECKBOX SETUJU */}
<div className="text-white text-sm">
<label className="flex items-center gap-2">
<input type="checkbox" className="w-4 h-4" />
saya setuju dengan syarat & ketentuan
</label>
</div>
<button
type="submit"
className="w-full bg-gray-500 text-white py-3 rounded-lg font-bold hover:bg-gray-700 transition"
>
register
</button>
</form>
</div>
</div>
);
}

2
package-lock.json generated
View File

@ -11,7 +11,7 @@
"isbot": "^5.1.36",
"react": "^19.2.4",
"react-dom": "^19.2.4",
"react-router": "7.14.0"
"react-router": "^7.14.0"
},
"devDependencies": {
"@react-router/dev": "7.14.0",

View File

@ -14,7 +14,7 @@
"isbot": "^5.1.36",
"react": "^19.2.4",
"react-dom": "^19.2.4",
"react-router": "7.14.0"
"react-router": "^7.14.0"
},
"devDependencies": {
"@react-router/dev": "7.14.0",
@ -26,4 +26,4 @@
"typescript": "^5.9.3",
"vite": "^8.0.3"
}
}
}