Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
b5da9ae
setting up components
christina-baldwin Apr 29, 2025
9c0008b
implementing the like counter
christina-baldwin Apr 29, 2025
1925326
fixing the function
christina-baldwin Apr 29, 2025
eb104d9
adding a dislike button and functionality
christina-baldwin Apr 29, 2025
17fe57b
getting the adding messages functionality to work
christina-baldwin Apr 29, 2025
5272c89
setting up na global styles and styling the layout of the form component
christina-baldwin Apr 29, 2025
b82ac43
linking and using the font-families
christina-baldwin Apr 29, 2025
a311959
getting the colours right
christina-baldwin Apr 29, 2025
286c075
implementing the "liked" colour-change functionality
christina-baldwin Apr 29, 2025
f180acd
more styling
christina-baldwin Apr 29, 2025
9b130c1
font size changes
christina-baldwin Apr 29, 2025
3253459
getting the time since posting to show (only on reload and in seconds)
christina-baldwin Apr 30, 2025
19a2c0c
removing destructuring
christina-baldwin May 2, 2025
340ca65
starting to migrate to tailwind
christina-baldwin May 5, 2025
2730500
fixing sizing and removing global styles
christina-baldwin May 5, 2025
cecbe07
migrating form styled components to tailwind
christina-baldwin May 5, 2025
10f1141
having the messages appear newest first
christina-baldwin May 5, 2025
398face
making the cursor over the button a pointer
christina-baldwin May 5, 2025
947ac30
getting the messages to show up newest first
christina-baldwin May 5, 2025
7b0e548
using tailwind in messages component
christina-baldwin May 6, 2025
b5b30c2
fetching messages, displaying them, and posting new messages to the API
christina-baldwin May 6, 2025
694fd48
getting the like functionality to work based on the likes documented …
christina-baldwin May 7, 2025
c3555ae
adding "unlike" functionality (waiting to see if API supports delete …
christina-baldwin May 7, 2025
b505038
functionality to disable message submission when over 140 characters
christina-baldwin May 7, 2025
df11c8f
removing message.trim
christina-baldwin May 7, 2025
c369da5
adding a liked messages component that shows how many messages the us…
christina-baldwin May 7, 2025
ffff7ad
making sure its responsive
christina-baldwin May 8, 2025
2861ab3
getting the time show seconds, minutes, days
christina-baldwin May 8, 2025
ab51dfa
creating an animation for when you post a new message
christina-baldwin May 8, 2025
52de530
not needing animate porescence
christina-baldwin May 8, 2025
7895436
removing uneeded import
christina-baldwin May 8, 2025
60c974e
loading the liked messages in a "liked messages" section
christina-baldwin May 12, 2025
0f0fd51
adding a main heading for the app
christina-baldwin May 12, 2025
abbb6b3
changing heading margin
christina-baldwin May 12, 2025
0a0c5da
moving liked messages furtehr down
christina-baldwin May 26, 2025
c7c7b87
adding word break to the message
christina-baldwin Jun 2, 2025
9d0d9ce
updating api links and some styling
christina-baldwin Jun 2, 2025
b54b0fa
settingup to accpet the new backend
christina-baldwin Jun 11, 2025
7d63976
fixing some linting errors
christina-baldwin Jun 11, 2025
389fd12
adding my own api routes
christina-baldwin Jun 12, 2025
8d47c7d
adding required pages
christina-baldwin Jun 12, 2025
be1e684
setting up my new pages
christina-baldwin Jun 12, 2025
a6a65b2
styling the log in page
christina-baldwin Jun 12, 2025
658db58
styling my register page
christina-baldwin Jun 12, 2025
1fc92b7
getting the styling to match
christina-baldwin Jun 12, 2025
002db71
adding links to login and register buttons and on the pages
christina-baldwin Jun 12, 2025
7b4185a
setting up my registration page to send to the backend
christina-baldwin Jun 13, 2025
ac6daf5
getting login to work with the backend
christina-baldwin Jun 13, 2025
df1b4da
getting messages to load and update
christina-baldwin Jun 13, 2025
ddada0b
fixing the message buttons styling
christina-baldwin Jun 13, 2025
e62756e
adding authorisation to like messages
christina-baldwin Jun 13, 2025
564ebdc
adding a log out button
christina-baldwin Jun 13, 2025
d08533a
matching the styling of the logout button
christina-baldwin Jun 13, 2025
04187e6
fixing some notes
christina-baldwin Jun 13, 2025
ba6a928
editing notes
christina-baldwin Jun 15, 2025
1a565a2
adding a loggon in state
christina-baldwin Jun 15, 2025
b5d7cdc
Merge pull request #1 from christina-baldwin/new-backend
christina-baldwin Jun 15, 2025
ac8db2b
changing so liked messages comes from checking the token instead of l…
christina-baldwin Jun 17, 2025
9b859be
typo fix
christina-baldwin Jun 17, 2025
7fb1443
Merge pull request #2 from christina-baldwin/liked-messages
christina-baldwin Jun 17, 2025
46af1fe
validation checks for registration form
christina-baldwin Aug 21, 2025
0409871
removing notes
christina-baldwin Aug 21, 2025
af03fe4
login validation
christina-baldwin Aug 21, 2025
96d4506
getting the delete and update handlers to work
christina-baldwin Aug 21, 2025
5afb333
fixing the like functionality
christina-baldwin Aug 21, 2025
8ad6799
removing old code
christina-baldwin Aug 21, 2025
ebdc15e
removed some notes
christina-baldwin Aug 21, 2025
fd15260
liking/unliking updates liked messages
christina-baldwin Aug 21, 2025
9c5e3a1
added a navigate back to login on succesful registration so UX is cle…
christina-baldwin Aug 25, 2025
bbf206a
making it easier tio change url
christina-baldwin Oct 18, 2025
c1991dc
log
christina-baldwin Oct 18, 2025
a59a8e4
fix
christina-baldwin Oct 18, 2025
3a6da90
move localStorage out of try catch
christina-baldwin Oct 18, 2025
7970e6a
Merge pull request #3 from christina-baldwin/liked-messages
christina-baldwin Oct 18, 2025
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
19 changes: 16 additions & 3 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,28 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="./vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />

<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;1,100;1,200;1,300;1,400;1,500;1,600;1,700&family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap"
rel="stylesheet"
/>
<link href="/src/index.css" rel="stylesheet" />

<title>Happy Thoughts</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="./src/main.jsx"></script>
<script
type="module"
src="./src/main.jsx">
</script>
src="https://unpkg.com/[email protected]/dist/ionicons/ionicons.esm.js"
></script>
<script
nomodule
src="https://unpkg.com/[email protected]/dist/ionicons/ionicons.js"
></script>
</body>
</html>
10 changes: 9 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,26 @@
"preview": "vite preview"
},
"dependencies": {
"@tailwindcss/vite": "^4.1.5",
"framer-motion": "^12.10.3",
"jwt-decode": "^4.0.0",
"react": "^19.0.0",
"react-dom": "^19.0.0"
"react-dom": "^19.0.0",
"react-router-dom": "^7.6.2",
"styled-components": "^6.1.17"
},
"devDependencies": {
"@eslint/js": "^9.21.0",
"@types/react": "^19.0.10",
"@types/react-dom": "^19.0.4",
"@vitejs/plugin-react": "^4.3.4",
"autoprefixer": "^10.4.21",
"eslint": "^9.21.0",
"eslint-plugin-react-hooks": "^5.1.0",
"eslint-plugin-react-refresh": "^0.4.19",
"globals": "^15.15.0",
"postcss": "^8.5.3",
"tailwindcss": "^4.1.5",
"vite": "^6.2.0"
}
}
1 change: 0 additions & 1 deletion public/vite.svg

This file was deleted.

19 changes: 16 additions & 3 deletions src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
import Landing from "./pages/Landing";
import Login from "./pages/Login";
import Main from "./pages/Main";
import Register from "./pages/Register";
import { Route, BrowserRouter as Router, Routes } from "react-router-dom";

export const App = () => {
return (
<h1>Happy Thoughts</h1>
)
}
<Router>
<Routes>
<Route path="/" element={<Landing />} />
<Route path="/register" element={<Register />} />
<Route path="/login" element={<Login />} />
<Route path="/app" element={<Main />} />
</Routes>
</Router>
);
};
89 changes: 89 additions & 0 deletions src/components/Form.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import React, { useState } from "react";

const url = "https://api-project-ns11.onrender.com";
// const url = "http://localhost:8080";

const Form = ({ setMessages }) => {
const [message, setMessage] = useState("");
const [errorMessage, setErrorMessage] = useState("");

const handleSubmit = async (e) => {
e.preventDefault();
const newMessage = { message };

if (message.length === 0) {
setErrorMessage("Can't submit an empty message!");
return;
}

if (message.length > 140) {
setErrorMessage("Message can't be longer than 140 characters!");
return;
}

setErrorMessage("");

try {
const token = localStorage.getItem("token"); // or wherever you store the JWT

const response = await fetch(`${url}/thoughts`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`, // include token here
},
body: JSON.stringify(newMessage),
});

if (!response.ok) {
throw new Error("Failed to post message");
}

const data = await response.json();
console.log("Message posted:", data);

setMessages((prev) => [data.response, ...prev]);

setMessage("");
} catch (error) {
console.error("Error posting message:", error);
}
};

return (
<form
onSubmit={handleSubmit}
className="flex flex-col justify-between gap-4 border border-black bg-[#f5f5f5] p-4 shadow-[4px_4px_0px_#000] mb-12"
>
<h1 className="text-base font-medium">
What is making you happy right now?
</h1>
<input
type="text"
onChange={(e) => setMessage(e.target.value)}
value={message}
className="font-mono h-[70px] px-2 text-sm font-normal border border-gray-400 rounded bg-white focus:outline-none focus:ring-2 focus:ring-pink-300"
/>
<p
className={`text-sm mt-2 ${
message.length > 140 ? "text-red-500 text-sm mt-2" : "text-[#333]"
}`}
>
Character count: {message.length}
</p>
{errorMessage && (
<p className="text-red-500 text-sm mt-2">{errorMessage}</p>
)}
<button
type="submit"
className="self-start flex items-center justify-center gap-1 px-3 py-2 border-none rounded-[15px] bg-pink-200 font-bold text-sm cursor-pointer hover:bg-pink-300 transition"
>
<ion-icon name="heart"></ion-icon>
Send Happy Thought
<ion-icon name="heart"></ion-icon>
</button>
</form>
);
};

export default Form;
65 changes: 65 additions & 0 deletions src/components/LikedMessages.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { useEffect, useState } from "react";

import Message from "./Message";

const getUserFromToken = () => {
const token = localStorage.getItem("token");
if (!token) return null;

try {
const base64Payload = token.split(".")[1];
const payload = JSON.parse(atob(base64Payload));
return payload.email || payload.id || null;
} catch (error) {
console.error("Invalid token", error);
return null;
}
};

const LikedMessages = ({ messages, onUpdateLike }) => {
const [likedMessages, setLikedMessages] = useState([]);

useEffect(() => {
const currentUser = getUserFromToken();
if (!currentUser) return;

const likedMessages = messages.filter((message) =>
message.likedBy?.includes(currentUser)
);
setLikedMessages(likedMessages);
}, [messages]);

return (
<div className="mb-20">
<div>
<h2 className="font-sans mb-6 text-2xl text-pink-500">
Liked Messages
</h2>
<div className="mb-4 text-right">
<h3 className="text-base text-gray-500 font-sans">
You have liked {likedMessages.length} message
{likedMessages.length === 1 ? "" : "s"}
</h3>
</div>
<div className="flex flex-col gap-12">
{likedMessages.length > 0 ? (
likedMessages.map((message) => (
<Message
key={message._id}
id={message._id}
message={message.message}
time={message.createdAt}
likes={message.hearts}
onUpdateLike={onUpdateLike}
/>
))
) : (
<p>No liked messages.</p>
)}
</div>
</div>
</div>
);
};

export default LikedMessages;
Loading