Skip to content
Merged
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
55 changes: 55 additions & 0 deletions frontend/src/components/MemeDaily.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { useEffect, useState } from "react";
import styled from "styled-components";

export const MemeOfTheDay = () => {
const [meme, setMeme] = useState(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
useEffect(() => {
const fetchMeme = async () => {
setLoading(true);
setError(null);
try {
const response = await fetch(
"https://meme-api.com/gimme/wholesomememes",
);
const data = await response.json();
setMeme(data);
} catch (err) {
setError("Ooops, couldn't fetch meme");
} finally {
setLoading(false);
}
};
fetchMeme();
}, []);

/* if (taskDone) {
fetchMeme();
}
}, */

if (loading) return <p>Loading your reward....</p>;
if (error) return <p>{error}</p>;

return (
<Container>
{loading && <p>loadingMeme</p>}
{error && <p>Error: {message}</p>}
{meme && <MemeImg src={meme.url} alt={meme.title}></MemeImg>}
</Container>
);
};

const Container = styled.div`
display: flex;
flex-direction: column;
align-items: center;
gap: 24px;
margin-bottom: 12px;
`;

const MemeImg = styled.img`
max-width: 100%;
border-radius: 12px;
`;
25 changes: 14 additions & 11 deletions frontend/src/pages/QuestPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,13 @@ const [state, dispatch] = useReducer(reducer, initialState)
// Get the live version of the quest from the store so checkbox stays in sync
const currentQuest = quests.find(quest => quest._id === state.randomQuest?._id)

const handleComplete = async (id, checked) => {
await completeQuest(id, checked)
if (checked) {
alert('Great work! 🎉')
navigate('/')
}
}
const handleComplete = async (id, checked) => {
await completeQuest(id, checked);
if (checked) {
//alert("Great work! 🎉");
navigate("/rewards");
}
};

const handleSubmit = async (e) => {
e.preventDefault()
Expand All @@ -63,16 +63,19 @@ const handleComplete = async (id, checked) => {
const freshQuests = await fetchQuests()

if (freshQuests.length === 0) {
dispatch({ type: 'noMatch', message: 'You have no quests yet!' })
return
dispatch({ type: "noMatch", message: "You have no quests yet!" });
return;
}

// Filter quests. Show only quests under chosen time frame
const filtered = freshQuests.filter(quest => quest.timeNeeded <= Number(state.timeAvailable))

if (filtered.length === 0) {
dispatch({ type: 'noMatch', message: `No quests under ${state.timeAvailable} minutes` })
return
dispatch({
type: "noMatch",
message: `Looks like you don't have quests under ${state.timeAvailable} minutes, try again!`,
});
return;
}

// Problem initially: gave random quest below requested time available, but could giv quest a LOT shorter then inputted time. Solved by: first sort timeNeeded closest to available time first.
Expand Down
102 changes: 101 additions & 1 deletion frontend/src/pages/RewardPage.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,105 @@
import styled from "styled-components";
import { useEffect, useState } from "react";

import { Link, Navigate, useNavigate } from "react-router-dom";
import { MemeOfTheDay } from "../components/MemeDaily";

export const Rewards = () => {
return <h1>Rewards page</h1>;
//check if quest is checked as done
//navigate from "get quest of the day" to "reward"
//fetch random meme from api
//prevent fetching new meme on refresh

const navigate = useNavigate();

const handleClick = (e) => {
e.preventDefault();
navigate("/");
};

return (
<PageWrapper>
<ButtonClose onClick={handleClick}>X</ButtonClose>
<h2>You are on fire today</h2>
<p>Keep it up and don't forget to smile!</p>
<MemeOfTheDay />
<ButtonReward onClick={handleClick}>Back home</ButtonReward>
</PageWrapper>
);
};

const PageWrapper = styled.div`
display: flex;
flex-direction: column;
gap: 12px;
justify-content: center;
align-items: center;
padding: 0 20px;
`;

const ButtonClose = styled.button`
padding: 4px;
border: none;
background-color: transparent;
width: 44px;
height: 44px;
margin-top: 24px;

font-size: 16px;
font-weight: 400;
color: var(--main-text-color);

align-self: flex-end;

&:hover {
border-radius: 12px;
font-weight: 600;
cursor: pointer;
transform: scale(1.05);
background-color: var(--light-purple);
}

&:active {
border-radius: 12px;
transform: scale(0.85);
background-color: var(--accent-purple);
}
`;

const ButtonReward = styled.button`
display: inline-flex;
height: 44px;
padding: 8px 16px;
justify-content: center;
align-items: center;
font-size: 16px;
font-style: normal;
font-weight: 400;
background-color: transparent;

border-radius: 12px;
border: 1px solid var(--medium-purple);

/* Small shadow */
box-shadow: 0 2px 2px 0 #dbdbdb;

&:hover {
font-weight: 500;
background-color: var(--light-purple);
transform: scale(1.05);
transition: ease-in-out;
}

&:active {
border: 1px solid var(--dark-purple);
background-color: var(--accent-purple);
transform: scale(0.85);
}
`;

//Fetch a random meme from api
//Show it to user in the questOftheDay after it is checked DONE
//button Close
//Button hahaha

// TODO: Put content here + set up route
2 changes: 1 addition & 1 deletion frontend/src/stores/useQuestStore.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const useQuestStore = create((set) => ({

// fetch all quests for the logged in user
fetchQuests: async (token) => {
const accessToken = token || useUserStore.getState().user?.accessToken
const accessToken = token || useUserStore.getState().user?.accessToken;

if (!accessToken) return [];

Expand Down