Skip to content
Open
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
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,13 @@ dist-ssr
*.njsproj
*.sln
*.sw?

# Environments
.env
.envrc
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
10 changes: 10 additions & 0 deletions package-lock.json

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

19 changes: 19 additions & 0 deletions src/api/get-bucketlist.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
async function getBucketlist(bucketlistId) {
const url = `${import.meta.env.VITE_API_URL}/bucketlists/${bucketlistId}`;
const response = await fetch(url, { method: "GET" });

if (!response.ok) {
const fallbackError = `Error fetching bucketlist with id ${bucketlistId}`;

const data = await response.json().catch(() => {
throw new Error(fallbackError);
});

const errorMessage = data?.detail ?? fallbackError;
throw new Error(errorMessage);
}

return await response.json();
}

export default getBucketlist;
171 changes: 171 additions & 0 deletions src/components/RegisterForm.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
import { useState } from "react";
//import postRegister from "../api/post-register.js";
//import postLogin from "../api/post-login.js";
import { useNavigate, useOutletContext } from "react-router-dom";

function RegisterForm() {
const navigateTo = useNavigate();
const { setIsLoggedIn } = useOutletContext();

const [formData, setFormData] = useState({
username: "",
email: "",
password: "",
password2: "",
firstName: "",
lastName: "",
});

const [errors, setErrors] = useState({});
const [isLoading, setIsLoading] = useState(false);

const handleChange = (event) => {
const { id, value } = event.target;
setFormData((prevData) => ({
...prevData,
[id]: value,
}));
// Clear error for this field when user starts typing
if (errors[id]) {
setErrors((prev) => ({ ...prev, [id]: "" }));
}
};

const handleSubmit = async (event) => {
event.preventDefault();
setErrors({});

// Validation
const newErrors = {};
if (!formData.username) newErrors.username = "Username is required";
if (!formData.email) newErrors.email = "Email is required";
if (!formData.password) newErrors.password = "Password is required";
if (formData.password !== formData.password2) {
newErrors.password2 = "Passwords don't match";
}

if (Object.keys(newErrors).length > 0) {
setErrors(newErrors);
return;
}

setIsLoading(true);

try {
// Register the user COME BACK TO THIS AFTER post-register.js and post-login.js are ACTIONED
//await postRegister(
//formData.username,
//formData.email,
//formData.password,
//formData.firstName,
//formData.lastName
//);

// Automatically log them in
//const loginResponse = await postLogin(formData.username, formData.password);
//window.localStorage.setItem("token", loginResponse.token);
//window.localStorage.setItem("userId", loginResponse.user_id);
//setIsLoggedIn(true);

// Redirect to home
//navigateTo("/account");
console.log("Register from submitted", formData);
navigateTo("/");
} catch (error) {
setErrors({ general: error.message || "Registration failed. Please try again." });
} finally {
setIsLoading(false);
}
};

return (
<form className="login-form" onSubmit={handleSubmit}>
{errors.general && (
<div className="error-message">{errors.general}</div>
)}

<div className="form-group">
<label htmlFor="username">Username *</label>
<input
type="text"
id="username"
placeholder="Choose a username"
value={formData.username}
onChange={handleChange}
disabled={isLoading}
/>
{errors.username && <span className="field-error">{errors.username}</span>}
</div>

<div className="form-group">
<label htmlFor="email">Email *</label>
<input
type="email"
id="email"
placeholder="[email protected]"
value={formData.email}
onChange={handleChange}
disabled={isLoading}
/>
{errors.email && <span className="field-error">{errors.email}</span>}
</div>

<div className="form-group">
<label htmlFor="firstName">First Name</label>
<input
type="text"
id="firstName"
placeholder="First name"
value={formData.firstName}
onChange={handleChange}
disabled={isLoading}
/>
</div>

<div className="form-group">
<label htmlFor="lastName">Last Name</label>
<input
type="text"
id="lastName"
placeholder="Last name"
value={formData.lastName}
onChange={handleChange}
disabled={isLoading}
/>
</div>

<div className="form-group">
<label htmlFor="password">Password *</label>
<input
type="password"
id="password"
placeholder="Create a password"
value={formData.password}
onChange={handleChange}
disabled={isLoading}
/>
{errors.password && <span className="field-error">{errors.password}</span>}
<p className="field-help">Password must be at least 8 characters long, and not too common</p>
</div>

<div className="form-group">
<label htmlFor="password2">Confirm Password *</label>
<input
type="password"
id="password2"
placeholder="Confirm your password"
value={formData.password2}
onChange={handleChange}
disabled={isLoading}
/>
{errors.password2 && <span className="field-error">{errors.password2}</span>}
</div>

<button type="submit" className="login-button" disabled={isLoading}>
{isLoading ? "Creating KickIt Account..." : "Sign Up"}
</button>
</form>
);
}

export default RegisterForm;
10 changes: 8 additions & 2 deletions src/main.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,14 @@ import Layout from "./layout";
import HomePage from "./pages/HomePage.jsx";
import LoginPage from "./pages/LoginPage.jsx";
import AccountPage from "./pages/AccountPage.jsx";
import BucketListsPage from "./pages/BucketListsPage";
import SingleListView from "./pages/SingleListView.jsx";
import RegisterPage from "./pages/RegisterPage";
import InviteAcceptPage from "./pages/InviteAcceptPage.jsx";

import { AuthProvider } from "./components/AuthProvider.jsx"
import GoogleOAuthCallback from "./components/GoogleOAuthCallback.jsx";
import NotFound from "./pages/NotFoundPage";
import "./main.css"

const router = createBrowserRouter([
Expand All @@ -23,10 +27,12 @@ const router = createBrowserRouter([
children: [
{ index: true, element: <HomePage /> },
{ path: "/login", element: <LoginPage />},
{ path: "/register", element: <RegisterPage />},
{ path: "/dashboard", element: <AccountPage />},
{ path: "/oauth/google/callback", element: <GoogleOAuthCallback /> },
{ path: "/invites/:token", element: <InviteAcceptPage /> },
{ path: "/bucketlists/:id", element: <HomePage /> },
{ path: "/bucketlists", element: <BucketListsPage /> },
{ path: "/bucketlists/:id", element: <SingleListView /> },
{ path: "*", element: <NotFound /> },
],
},
]);
Expand Down
36 changes: 0 additions & 36 deletions src/pages/AccountPage.jsx

This file was deleted.

3 changes: 3 additions & 0 deletions src/pages/BucketListsPage.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function BucketListsPage() {
return <h1>Bucket Lists</h1>
}
2 changes: 1 addition & 1 deletion src/pages/LoginPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,4 +118,4 @@ function LoginPage() {
);
}

export default LoginPage;
export default LoginPage;
10 changes: 10 additions & 0 deletions src/pages/NotFoundPage.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Link } from "react-router-dom";

export default function NotFound() {
return (
<div>
<h1>404 - Page Not Found</h1>
<Link to="/">Back to Home</Link>
</div>
)
}
19 changes: 19 additions & 0 deletions src/pages/RegisterPage.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Link } from "react-router-dom";
import RegisterForm from "../components/RegisterForm";

function RegisterPage() {
return (
<div className="login-page">
<div className="login-container">
<h1 className="login-title">Create Account</h1>
<p className="login-subtitle">Join Bucket List</p>
<RegisterForm />
<div className="login-footer">
Already have an account? <Link to="/log">Login here</Link>
</div>
</div>
</div>
);
}

export default RegisterPage;
Loading