Skip to content

Commit

Permalink
Merge pull request #10 from yusufalperendumlu/V1.0.0/feature/user-ope…
Browse files Browse the repository at this point in the history
…ration

V1.0.0/feature/user operation
  • Loading branch information
yusufalperendumlu authored May 6, 2024
2 parents 6bb4767 + 7e05f7e commit 4e7dbec
Show file tree
Hide file tree
Showing 12 changed files with 384 additions and 34 deletions.
21 changes: 20 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
"react-hot-toast": "^2.4.1",
"react-icons": "^5.2.0",
"react-router-dom": "^6.23.0",
"react-toastify": "^10.0.5"
"react-toastify": "^10.0.5",
"sweetalert2": "^11.10.8"
},
"devDependencies": {
"@types/react": "^18.0.37",
Expand Down
2 changes: 2 additions & 0 deletions src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import HomePage from "@/pages/home/HomePage";
import RegisterPage from "@/pages/register/RegisterPage";
import ProfilePage from "@/pages/profile/ProfilePage";
import CarsShow from "@/pages/carsShow/CarsShow";
import VerifyEmailPage from "@/pages/verify/VerifyEmailPage";

function App() {
return (
Expand All @@ -13,6 +14,7 @@ function App() {
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/register" element={<RegisterPage />} />
<Route path="/verifyEmail" element={<VerifyEmailPage />} />
<Route path="/profile" element={<ProfilePage />} />
<Route path="/rent/1" element={<CarsShow />} />
</Routes>
Expand Down
Binary file added src/assets/c2_credits.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
82 changes: 59 additions & 23 deletions src/components/Header.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useEffect, useState } from "react";
import { Link } from "react-router-dom";
import { Link, useNavigate } from "react-router-dom";
import { IoIosArrowDown } from "react-icons/io";
import { AiOutlineMenu, AiOutlineClose, AiOutlineLogin } from "react-icons/ai";
import { clsx } from "clsx";
Expand Down Expand Up @@ -123,6 +123,8 @@ const NavItem = ({ item }) => {
};

const Header = () => {
const navigate = useNavigate();
const [profileDropdown, setProfileDropdown] = useState(false);
const [navIsVisible, setNavIsVisible] = useState(false);
const [LoginIsVisible, setLoginIsVisible] = useState(false);
const [scrollPosition, setScrollPosition] = useState(0);
Expand All @@ -149,13 +151,9 @@ const Header = () => {
});
};

// useEffect(() => {
// const handleClickOutside = (e) => {
// if (loginRef.current && !loginRef.current.contains(e.target)) {
// setLoginIsVisible(false);
// }
// };
// });
const logoutHandler = () => {
localStorage.removeItem("account");
};

return (
<section
Expand Down Expand Up @@ -201,24 +199,62 @@ const Header = () => {
<div className="relative">
<div className="flex">
<span className="px-4 flex items-center justify-center">|</span>
<button
onClick={loginVisibilityHandler}
className={clsx(
"flex items-center flex-nowrap gap-2 my-2 mx-4 hover:text-white transition-all duration-500 ease-linear relative group",
LoginIsVisible && "text-white"
)}
>
<span>Login</span>
<AiOutlineLogin className="w-6 h-6" />
<span
{localStorage.getItem("account") ? (
<div className="text-white items-center gap-y-5 lg:text-dark-soft flex flex-col lg:flex-row gap-x-3 font-semibold">
<div className="relative group">
<div className="flex flex-col items-center">
<p className="flex cursor-pointer gap-x-1 items-center mt-5 lg:mt-0 border-2 border-blue-500 px-6 py-2 rounded-full text-blue-500 font-semibold hover:bg-blue-500 hover:text-white transition-all duration-300">
<span>Account</span>
<IoIosArrowDown
onClick={() => setProfileDropdown(!profileDropdown)}
/>
</p>
<div
className={clsx(
"lg:hidden transition-all duration-500 pt-4 absolute bottom-0 right-0 transform translate-y-full w-max lg:group-hover:block z-50 opacity-100",
profileDropdown ? "hidden" : "block"
)}
>
<ul className="flex flex-col z-50 bg-dark-hard lg:bg-white shadow-lg rounded-lg overflow-hidden ">
<button
type="button"
onClick={() => navigate("/profile")}
className="hover:bg-dark-hard hover:text-white px-4 py-2 text-white lg:text-dark-hard"
>
Profile Page
</button>
<button
onClick={logoutHandler}
type="button"
className="hover:bg-dark-hard hover:text-white px-4 py-2 text-white lg:text-dark-hard"
>
Logout
</button>
</ul>
</div>
</div>
</div>
</div>
) : (
<button
onClick={loginVisibilityHandler}
className={clsx(
"text-yellow-400 absolute right-0 top-0 opacity-0 transition-all duration-500 font-bold group-hover:opacity-100 group-hover:right-[100%] group-hover:mr-2 ",
LoginIsVisible && "opacity-100 right-[100%] mr-2"
"flex items-center flex-nowrap gap-2 my-2 mx-4 hover:text-white transition-all duration-500 ease-linear relative group",
LoginIsVisible && "text-white"
)}
>
🗲
</span>
</button>
<span>Login</span>
<AiOutlineLogin className="w-6 h-6" />
<span
className={clsx(
"text-yellow-400 absolute right-0 top-0 opacity-0 transition-all duration-500 font-bold group-hover:opacity-100 group-hover:right-[100%] group-hover:mr-2 ",
LoginIsVisible && "opacity-100 right-[100%] mr-2"
)}
>
🗲
</span>
</button>
)}
<div className="absolute hidden top-14 right-0 lg:block group-hover">
{LoginIsVisible && <Login />}
</div>
Expand Down
76 changes: 71 additions & 5 deletions src/components/modal/Login.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import clsx from "clsx";
import { useState } from "react";
import { Link } from "react-router-dom";
import { useMutation } from "@tanstack/react-query";
import { Link, useNavigate } from "react-router-dom";
import { IoIosArrowDown, IoIosEye, IoIosEyeOff } from "react-icons/io";
import { toast } from "react-toastify";
import clsx from "clsx";

import { signIn } from "@/services/index/users";
import { useForm } from "react-hook-form";
import Swal from "sweetalert2";

const Login = () => {
const navigate = useNavigate();

const [showPassword, setShowPassword] = useState(false);
const [password, setPassword] = useState("");

Expand All @@ -15,6 +23,48 @@ const Login = () => {
setPassword(e.target.value);
};

const { mutate, isLoading } = useMutation({
mutationFn: ({ email, password }) => {
return signIn({ email, password });
},
onSuccess: (data) => {
localStorage.setItem("account", JSON.stringify(data));
Swal.fire({
icon: "success",
title: "Login Successful",
text: "You have successfully logged in",
});
navigate("/");
},
onError: (error) => {
Swal.fire({
icon: "error",
title: "Error",
text: error.message,
confirmButtonText: "OK",
});
},
});

const {
register,
handleSubmit,
formState: { errors, isValid },
// reset,
} = useForm({
defaultValues: {
email: "",
password: "",
},

mode: "onChange",
});

const submitHandler = (data) => {
const { email, password } = data;
mutate({ email, password });
};

return (
<div className="flex justify-center items-center bg-white p-2 w-full rounded-md shadow-lg ">
<div className="w-96 p-8 bg-dark-hard rounded-lg border-4 border-dark-light ">
Expand All @@ -25,7 +75,7 @@ const Login = () => {
You can log in with your{" "}
<span className="text-red-500">Individual Account</span>
</h1>
<form className="mt-8">
<form className="mt-8" onSubmit={handleSubmit(submitHandler)}>
<div className="mb-4">
<label
htmlFor="email"
Expand All @@ -37,6 +87,13 @@ const Login = () => {
type="email"
id="email"
name="email"
{...register("email", {
required: "Email is required",
pattern: {
value: /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/,
message: "Invalid email format",
},
})}
placeholder="E-Mail Address"
className="mt-2 block w-full h-12 px-3 py-2 border-none bg-dark-light rounded-md text-lg font-bold shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm focus:bg-white transition-all duration-200 ease-linear"
/>
Expand All @@ -63,12 +120,20 @@ const Login = () => {
type={showPassword ? "text" : "password"}
id="password"
name="password"
{...register("password", {
required: "Password is required",
minLength: {
value: 6,
message: "Password must be at least 6 characters",
},
})}
value={password}
onChange={handlePasswordChange}
placeholder="Password"
className={clsx(
"relative mt-2 block w-full h-12 px-3 py-2 border-none bg-dark-light rounded-md text-lg font-bold shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm focus:bg-white transition-all duration-200 ease-linear ",
{ "bg-white": !!password }
"relative block w-full h-12 px-3 py-2 border-none bg-dark-light rounded-md text-lg font-bold shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm focus:bg-white transition-all duration-200 ease-linear ",
{ "bg-white": !!password },
errors.password ? "mt-10" : "mt-2"
)}
/>
<button
Expand Down Expand Up @@ -96,6 +161,7 @@ const Login = () => {
</div>
<button
type="submit"
disabled={!isValid || isLoading}
className="w-1/2 py-2 border border-transparent rounded-full shadow-sm text-sm font-medium text-white bg-red-500 hover:bg-red-700 transition-all duration-300 ease-linear focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
>
Login
Expand Down
2 changes: 2 additions & 0 deletions src/constants/images.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import Doc from "@/assets/Doc9.jpg";
import DocFooter from "@/assets/Doc10.jpg";
import LuigiGuido from "@/assets/LuigiGuido8.jpg";
import LuigiGuido2 from "@/assets/LuigiGuido10.jpg";
import Cars2England from "@/assets/c2_credits.jpg";

const images = {
LogoImage,
Expand All @@ -22,6 +23,7 @@ const images = {
DocFooter,
LuigiGuido,
LuigiGuido2,
Cars2England,
};

export default images;
2 changes: 1 addition & 1 deletion src/pages/home/container/Hero.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const Hero = () => {
Now
<p>It&apos;s easy for you rent a car</p>
</h1>
<p className="text-dark-light mt-4 text-center md:text-lg lg:text-base xl:text-xl lg:text-left">
<p className="text-[#ffffff] mt-4 text-center md:text-lg lg:text-base xl:text-xl lg:text-left">
A small river named Duden flows by their place and supplies it with
the necessary regelialia. It is a paradisematic country, in which
roasted parts of sentences fly into your mouth.
Expand Down
2 changes: 1 addition & 1 deletion src/pages/register/RegisterPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const RegisterPage = () => {

const handleCloseConfirmed = () => {
setIsConfirmedOpen(false);
navigate("/");
navigate("/verifyEmail");
};

const handleCloseError = () => {
Expand Down
Loading

0 comments on commit 4e7dbec

Please sign in to comment.