first commmit
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
import { useState } from "react";
|
||||
import axios from "axios";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
const AuthForm = () => {
|
||||
const [formData, setFormData] = useState({ username: "", password: "" });
|
||||
const navigate = useNavigate();
|
||||
|
||||
const API_BASE = "/api";
|
||||
|
||||
const handleSubmit = async (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
try {
|
||||
const response = await axios.post(`${API_BASE}/login`, formData);
|
||||
const data = response.data;
|
||||
|
||||
if (data.token) {
|
||||
localStorage.setItem("token", data.token);
|
||||
localStorage.setItem("user", JSON.stringify(data.user));
|
||||
localStorage.removeItem("error");
|
||||
navigate("/");
|
||||
}
|
||||
} catch (err) {
|
||||
let errorMessage =
|
||||
err.response?.data?.error || err.message || "Неверный логин или пароль";
|
||||
const errorLog = {
|
||||
message: errorMessage,
|
||||
};
|
||||
localStorage.setItem("error", JSON.stringify(errorLog));
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex min-h-screen items-center justify-center bg-gray-100 px-4">
|
||||
<div className="w-full max-w-md space-y-8 rounded-lg bg-white p-10 shadow-md">
|
||||
<h2 className="text-center text-3xl font-bold text-gray-900">
|
||||
Вход в FISHFISH
|
||||
</h2>
|
||||
|
||||
<form className="mt-8 space-y-6" onSubmit={handleSubmit}>
|
||||
<div className="rounded-md shadow-sm space-y-px">
|
||||
<input
|
||||
type="text"
|
||||
required
|
||||
className="relative block w-full rounded-t-md border border-gray-300 px-3 py-2 text-gray-900 focus:border-blue-500 focus:outline-none sm:text-sm"
|
||||
placeholder="Логин"
|
||||
value={formData.username}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, username: e.target.value })
|
||||
}
|
||||
/>
|
||||
<input
|
||||
type="password"
|
||||
required
|
||||
className="relative block w-full rounded-b-md border border-gray-300 px-3 py-2 text-gray-900 focus:border-blue-500 focus:outline-none sm:text-sm"
|
||||
placeholder="Пароль"
|
||||
value={formData.password}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, password: e.target.value })
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{localStorage.getItem("error") && (
|
||||
<p className={`text-sm text-red-500`}>
|
||||
{JSON.parse(localStorage.getItem("error"))["message"] || ""}
|
||||
</p>
|
||||
)}
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
className="group relative flex w-full justify-center rounded-md bg-blue-600 px-4 py-2 text-sm font-medium text-white hover:bg-blue-700"
|
||||
>
|
||||
Войти
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AuthForm;
|
||||
@@ -0,0 +1,60 @@
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import siteLogo from "../assets/Исходники/logo.png";
|
||||
|
||||
export default function Header() {
|
||||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
<footer className="bg-light-blue w-full h-27.5 px-16 flex items-center justify-between ">
|
||||
<div className="flex flex-col items-center gap-2 text-lg tracking-widest text-gold">
|
||||
<img src={siteLogo} alt="Лого" className="w-12 h-12 object-contain" />
|
||||
<span>FISH FISH</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-8 text-lg uppercase tracking-wider text-light-gray">
|
||||
<button
|
||||
className="hover:text-gold duration-200 transition uppercase"
|
||||
onClick={() => navigate("/")}
|
||||
>
|
||||
fish fish
|
||||
</button>
|
||||
<svg
|
||||
width="4"
|
||||
height="4"
|
||||
viewBox="0 0 4 4"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<circle cx="2" cy="2" r="2" fill="white" />
|
||||
</svg>
|
||||
<button
|
||||
className="hover:text-gold duration-200 transition uppercase"
|
||||
onClick={() => navigate("/shop")}
|
||||
>
|
||||
ассортимент
|
||||
</button>
|
||||
<svg
|
||||
width="4"
|
||||
height="4"
|
||||
viewBox="0 0 4 4"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<circle cx="2" cy="2" r="2" fill="white" />
|
||||
</svg>
|
||||
<button
|
||||
className="hover:text-gold duration-200 transition uppercase"
|
||||
onClick={() => navigate("/about")}
|
||||
>
|
||||
контакты
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center">
|
||||
<button className="text-light-gray hover:text-gold transition-colors duration-200">
|
||||
+7 (800) 900-20-20
|
||||
</button>
|
||||
</div>
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import siteLogo from "../assets/Исходники/logo.png";
|
||||
|
||||
export default function Header() {
|
||||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
<header className="w-full h-27.5 px-16 flex items-center justify-between ">
|
||||
<div className="flex flex-col items-center gap-2 text-lg tracking-widest text-gold">
|
||||
<img src={siteLogo} alt="Лого" className="w-12 h-12 object-contain" />
|
||||
<span>FISH FISH</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-8 text-lg uppercase tracking-wider text-white">
|
||||
<button
|
||||
className="hover:text-gold duration-200 transition uppercase"
|
||||
onClick={() => navigate("/")}
|
||||
>
|
||||
fish fish
|
||||
</button>
|
||||
<svg
|
||||
width="4"
|
||||
height="4"
|
||||
viewBox="0 0 4 4"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<circle cx="2" cy="2" r="2" fill="white" />
|
||||
</svg>
|
||||
<button
|
||||
className="hover:text-gold duration-200 transition uppercase"
|
||||
onClick={() => navigate("/shop")}
|
||||
>
|
||||
ассортимент
|
||||
</button>
|
||||
<svg
|
||||
width="4"
|
||||
height="4"
|
||||
viewBox="0 0 4 4"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<circle cx="2" cy="2" r="2" fill="white" />
|
||||
</svg>
|
||||
<button
|
||||
className="hover:text-gold duration-200 transition uppercase"
|
||||
onClick={() => navigate("/about")}
|
||||
>
|
||||
контакты
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center">
|
||||
<button className="text-slate-200 hover:text-gold transition-colors duration-200 pr-7">
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<circle
|
||||
cx="12"
|
||||
cy="7.5"
|
||||
r="4"
|
||||
stroke="currentColor"
|
||||
strokeLinecap="square"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M21 21H3C3 17.6863 5.68629 15 9 15H15C18.3137 15 21 17.6863 21 21Z"
|
||||
stroke="currentColor"
|
||||
strokeLinecap="square"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
<button className="text-slate-200 hover:text-gold transition-colors duration-200">
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M16.2654 8H7.73459C6.73929 8 5.89545 8.73186 5.75469 9.71716L4.32612 19.7172C4.154 20.922 5.08892 22 6.30602 22H17.694C18.9111 22 19.846 20.922 19.6739 19.7172L18.2453 9.71716C18.1046 8.73186 17.2607 8 16.2654 8Z"
|
||||
stroke="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M9 10V5C9 3.89543 9.89543 3 11 3H13C14.1046 3 15 3.89543 15 5V10"
|
||||
stroke="currentColor"
|
||||
/>
|
||||
<circle cx="9" cy="10" r="1" fill="currentColor" />
|
||||
<circle cx="15" cy="10" r="1" fill="currentColor" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user