Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Origin/implement login page/ login signup pages components #78

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 25 additions & 18 deletions frontend/src/app/(authenticated)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,43 +1,50 @@
"use client"

import Navbar from "@/components/layouts/navbar"
import Sidebar from "@/components/layouts/sidebar"
import { Toaster } from "@/components/ui/toaster"
import React, { ReactNode, useState } from "react"
import {
QueryClient,
QueryClientProvider,
useQuery,
} from "@tanstack/react-query"
// components/layouts/authenticated-layout.tsx
lylaaron98 marked this conversation as resolved.
Show resolved Hide resolved

lylaaron98 marked this conversation as resolved.
Show resolved Hide resolved
import Navbar from "@/components/layouts/navbar";
import Sidebar from "@/components/layouts/sidebar";
import { Toaster } from "@/components/ui/toaster";
import React, { ReactNode, useState } from "react";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";

interface AuthenticatedLayoutProps {
children: ReactNode
children: ReactNode;
}

export default function AuthenticatedLayout({
children,
}: AuthenticatedLayoutProps) {
const queryClient = new QueryClient()
const queryClient = new QueryClient();

const [isSidebarOpen, setIsSidebarOpen] = useState(true)
const [isSidebarOpen, setIsSidebarOpen] = useState(true);

const toggleSidebar = () => {
setIsSidebarOpen((isSidebarOpen) => !isSidebarOpen)
}
setIsSidebarOpen((isSidebarOpen) => !isSidebarOpen);
};

return (
<QueryClientProvider client={queryClient}>
<div className="flex flex-row w-full min-h-[100vh]">
{/* Sidebar */}
<Sidebar
className={` ${isSidebarOpen ? "min-w-[280px] w-[280px]" : "min-w-0 w-0"} overflow-x-hidden transition-width duration-300 ease-in-out`}
className={`${
isSidebarOpen ? "min-w-[280px] w-[280px]" : "min-w-0 w-0"
} overflow-x-hidden transition-width duration-300 ease-in-out`}
/>

{/* Main Content */}
<div className="w-full">
{/* Navbar */}
<Navbar toggleSidebar={toggleSidebar} />

{/* Main Content Wrapper */}
<div className="w-full h-full max-h-[90vh] flex justify-center items-center flex-col relative">
<div className="w-5/6 h-full relative">{children}</div>
</div>
</div>

{/* Toaster */}
<Toaster />
</div>
</QueryClientProvider>
)
);
}
lylaaron98 marked this conversation as resolved.
Show resolved Hide resolved
53 changes: 53 additions & 0 deletions frontend/src/app/login/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import Link from "next/link";
import React, { useState } from "react";
import axios from "axios";
import { toast } from "react-hot-toast";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't use another toast library. There is already an existing toast component you can use. Also in my opinion, no need to use toast here. Simply login on success or display error below the form field if any. This can be done with the existing shadcn ui form component (Guide)

import LoginForm from "../components/form/loginForm";
import PageLayout from "../components/layout/pageLayout";
import InputField from "../components/ui/inputField";

export default function LoginPage() {
const [loading, setLoading] = useState(false);

const onLogin = async (user) => {
try {
setLoading(true);
const response = await axios.post("/api/users/login", user);
Copy link
Collaborator

@Ziyang-98 Ziyang-98 Mar 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you usin axios already when there is no backend api for login? /api/users/login does not exist. Please remove this to prevent invalid and unnecessary API calls.

console.log("Login success", response.data);
toast.success("Login success");
// router.push("/profile");
} catch (error) {
console.log("Login failed", error.message);
toast.error(error.message);
} finally {
setLoading(false);
}
};

return (
<PageLayout title={loading ? "Processing" : "Login"} loading={loading}>
<LoginForm onLogin={onLogin} />
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this importing an empty component?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to import this form component since you already have form input fields in the same file

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PageLayout is from flowforge\frontend\src\components\layouts\pageLayout.tsx
while LoginForm is from flowforge\frontend\src\components\form\loginForm.tsx

I've recommitted the changes to origin again. maybe the first commit did not register the saved changes.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your new commit only pushed inputField.tsx. The other files are still empty

<InputField
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is input field?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inputField is a component I created under frontend\src\components\ui\inputField.tsx

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image
inputField.tsx, component under flowforge\frontend\src\components\ui\inputField.tsx

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shld I remove the components ive created and instead utilise the existing ones? thought its easier since its kind of different. lmk thanks!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes please use the shadcn ui components we have for consistency. It is easier to implement with them as compared to vanilla HTML since its a library with pre-coded logic. We don't want to introduce other libs also.

id="email"
type="text"
value={user.email}
onChange={(value) => setUser({ ...user, email: value })}
placeholder="email"
/>
<InputField
id="password"
type="password"
value={user.password}
onChange={(value) => setUser({ ...user, password: value })}
placeholder="password"
/>
<button
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use our existing shadcn ui button component for consistent UI

onClick={onLogin}
className="p-2 border border-gray-300 rounded-lg mb-4 focus:outline-none focus:border-gray-600"
>
Login
</button>
<Link href="/signup">Visit Signup page</Link>
</PageLayout>
);
}
33 changes: 33 additions & 0 deletions frontend/src/app/signup/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import Link from "next/link";
import React, { useState } from "react";
import axios from "axios";
import { toast } from "react-hot-toast";
import SignupForm from "../components/form/signupForm";
import PageLayout from "../components/layout/pageLayout";
import InputField from "../components/ui/inputField";

export default function SignupPage() {
const [loading, setLoading] = useState(false);

const onSignup = async (user) => {
try {
setLoading(true);
const response = await axios.post("/api/users/signup", user);
console.log("Signup success", response.data);
toast.success("Signup success");
// router.push("/login");
} catch (error) {
console.log("Signup failed", error.message);
toast.error(error.message);
} finally {
setLoading(false);
}
};

return (
<PageLayout title={loading ? "Processing" : "Signup"} loading={loading}>
<SignupForm onSignup={onSignup} />
<Link href="/login">Visit login page</Link>
</PageLayout>
);
}
Copy link
Collaborator

@Ziyang-98 Ziyang-98 Mar 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

loginForm.tsx, signupForm.tsx and pageLayout.tsx are still empty files

Empty file.
Empty file.
Empty file.
19 changes: 19 additions & 0 deletions frontend/src/components/ui/inputField.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from "react";

const InputField = ({ id, type, value, onChange, placeholder }) => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are using Typescript so this should flag out an error since the props type is not defined

return (
<div>
<label htmlFor={id}>{id}</label>
<input
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

try to use the shadcn ui components we have. Can look here for details on how to use.

className="p-2 border border-gray-300 rounded-lg mb-4 focus:outline-none focus:border-gray-600 text-black"
id={id}
type={type}
value={value}
onChange={(e) => onChange(e.target.value)}
placeholder={placeholder}
/>
</div>
);
};

export default InputField;