Hey there! I recently completed an exciting project called Face Detective, and I wanted to share my experience with you. While this began as a tutorial project, I decided to make it my own by incorporating various technologies and features that sparked my interest. Some of the technologies I used include Tailwind CSS, React hooks, functional components, and Vite, which replaced Create React App for this project. I also added custom functionality like a route to check for matching passwords.
So, let's dive into the details of how I built the Face Detective web app!
Leveraging Tailwind CSS
One of my first steps was to give the project a sleek and modern look using Tailwind CSS. I found it incredibly helpful and efficient for quickly styling my components. Here's an example of how I styled the SignIn component using Tailwind CSS:
<div className="sm:mx-auto sm:w-full sm:max-w-md">
<h2 className="mt-6 text-center text-3xl font-bold tracking-tight text-violet-700">
Sign in to your account
</h2>
<p className="mt-2 text-center text-md text-white">
Or{" "}
<a
onClick={() => onRouteChange("register")}
href="#"
className="font-bold text-violet-500 hover:text-violet-600"
>
register for an account
</a>
</p>
</div>;
React Hooks and Functional Components
I chose to use React hooks and functional components for my project because they provide a clean and efficient way to manage state and side effects. I found this approach particularly helpful when working on the SignIn and Register components.
Here's an example of how I used the useState hook in the SignIn component:
import React, { useState } from "react";
const SignIn = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
// more code
};
I also leveraged the useEffect hook in the App component to fetch data when the component mounts:
useEffect(() => {
// Retrieve saved email and timestamp from localStorage
const savedEmail = localStorage.getItem("email");
const savedTimestamp = localStorage.getItem("emailTimestamp");
// Check if saved email and timestamp exist
if (savedEmail && savedTimestamp) {
const currentDate = new Date();
const savedDate = new Date(Number(savedTimestamp));
const daysPassed = (currentDate - savedDate) / (1000 * 60 * 60 * 24);
// Check if saved email is within the 14-day limit
if (daysPassed <= 14) {
setEmail(savedEmail);
setRememberMe(true);
} else {
// Clear saved email and timestamp if the 14-day limit has passed
localStorage.removeItem("email");
localStorage.removeItem("emailTimestamp");
}
}
}, []);
In the next sections, I'll share more about the challenges I faced and how I overcame them to build the Face Detective web app. Stay tuned!
Challenges and Problem Solving
As with any project, I encountered a few challenges along the way. One such challenge was ensuring the SignIn and Register components sent the proper information back to the database. Initially, I struggled to send and receive the correct data, but with persistence and some creative problem-solving, I managed to overcome this hurdle.
For instance, here's the code snippet for handling the SignIn form submission:
const handleSubmit = async (e) => {
e.preventDefault();
let hasError = false;
let errorMessages = [];
// some code
const signInResult = await handleSignIn(email, password);
if (signInResult) {
loadUser({
userId: signInResult.userId,
name: signInResult.name,
email: signInResult.email,
entries: signInResult.entries,
joined: signInResult.joined,
});
// more code
}
};
Initially when the sign in or registration form was submitted, the user would be transferred to the home page. They should have been able to see their name and number of entries, but instead, the name was blank and the entries said "user not found'. It turned out that I needed to update my call to loadUser()
to return the user object. It was a tricky bug to fix, but thank goodness for console.log
.
Another challenge I tackled was creating a custom route to check for existing emails. This functionality wasn't part of the tutorial, but I decided to implement it to add an extra layer of validation to the registration process. Here's the code for the existing email check:
app.post("/check-email", (req, res) => {
const { email } = req.body;
database("users")
.select("email")
.where("email", email)
.then((result) => {
if (result.length > 0) {
res.status(400).json({ message: "Email already exists" });
} else {
res.json({ message: "Email is available" });
}
})
.catch((err) => {
console.error("Error in /check-email route:", err); // Add this line for more detailed logging
res.status(500).json({ message: "Error checking email availability" });
});
});
Before writing the code above, the issue was that the /check-email
endpoint was using the database('users').where('email', email)
method, which returned a query builder, but I never executed the query. Therefore, it would always evaluate to a truthy value. I had to use .select()
and .then()
to execute the query and process the result.
Future Enhancements
The Face Detective App is a work in progress, and I plan to continually improve and expand its features. Some upcoming additions include:
User sessions: Implementing user authentication and maintaining sessions for a seamless experience.
Profile page: Adding a dedicated profile page to display user information and settings.
Account deletion: Giving users the option to delete their account and all associated data.
And more! I'm always exploring new ideas to make the app more robust and user-friendly.
Conclusion
Building the Face Detective web app has been an invaluable learning experience. It allowed me to hone my skills in various technologies like Tailwind CSS, React hooks, functional components, and Vite. Additionally, it gave me the opportunity to apply problem-solving techniques and creativity to overcome challenges and enhance the app's functionality.
I'm excited to continue working on the Face Detective App and sharing my progress with you. If you're interested in checking out the project demo, visit https://face-detective.ritabradley.dev/. Feel free to share your thoughts and feedback!
Happy coding!
Top comments (0)