diff --git a/frontend/src/components/MemeDaily.jsx b/frontend/src/components/MemeDaily.jsx new file mode 100644 index 0000000000..17d29bdc62 --- /dev/null +++ b/frontend/src/components/MemeDaily.jsx @@ -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

Loading your reward....

; + if (error) return

{error}

; + + return ( + + {loading &&

loadingMeme

} + {error &&

Error: {message}

} + {meme && } +
+ ); +}; + +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; +`; diff --git a/frontend/src/pages/QuestPage.jsx b/frontend/src/pages/QuestPage.jsx index 32fc98a16c..b88d8fc303 100644 --- a/frontend/src/pages/QuestPage.jsx +++ b/frontend/src/pages/QuestPage.jsx @@ -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() @@ -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. diff --git a/frontend/src/pages/RewardPage.jsx b/frontend/src/pages/RewardPage.jsx index eb60e560a3..682b9bc5e4 100644 --- a/frontend/src/pages/RewardPage.jsx +++ b/frontend/src/pages/RewardPage.jsx @@ -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

Rewards page

; + //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 ( + + X +

You are on fire today

+

Keep it up and don't forget to smile!

+ + Back home +
+ ); }; +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 diff --git a/frontend/src/stores/useQuestStore.jsx b/frontend/src/stores/useQuestStore.jsx index f3bdcad0df..7396c2a2c7 100644 --- a/frontend/src/stores/useQuestStore.jsx +++ b/frontend/src/stores/useQuestStore.jsx @@ -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 [];