feat: initial import — ClickerZ formation project (Express + React/Vite)

This commit is contained in:
2026-03-15 14:29:33 +01:00
commit 4e93753250
118 changed files with 71039 additions and 0 deletions

View File

@@ -0,0 +1,28 @@
import "../scss/components/achievementscard.scss";
import PropTypes from "prop-types";
function AchievementsCard({ name, description, image, key }) {
AchievementsCard.propTypes = {
name: PropTypes.string.isRequired,
description: PropTypes.string.isRequired,
image: PropTypes.string.isRequired,
key: PropTypes.number.isRequired,
};
return (
<div className="achievCardcontainer">
<img
className="achievecardpicture"
key={key}
src={image}
alt="cartes speciales"
/>
<div className="achievetitle">
<p className="achievname">{name}</p>
<p className="achievdescription">{description}</p>
</div>
</div>
);
}
export default AchievementsCard;

View File

@@ -0,0 +1,130 @@
import { useWildCoin } from "./WildCoin/WildCoinContext";
import "../scss/components/boutiquecard.scss";
import "../scss/components/buttons.scss";
import PropTypes from "prop-types";
export default function BoutiqueCard({
name,
price,
incrementValue,
description,
image,
link,
type,
buyed,
}) {
BoutiqueCard.propTypes = {
name: PropTypes.string.isRequired,
price: PropTypes.number.isRequired,
incrementValue: PropTypes.number.isRequired,
description: PropTypes.string.isRequired,
image: PropTypes.string.isRequired,
link: PropTypes.string.isRequired,
type: PropTypes.string.isRequired,
buyed: PropTypes.bool.isRequired,
};
const {
wildCoin,
incrementClick,
setWildCoin,
setIncrementClick,
incrementPerSecond,
setIncrementPerSecond,
setCoffee,
setSantaDrunk,
setManic,
setSnowman,
setBonnet,
setSugar,
setCookie,
setCouronne,
setEpice,
setBiere,
} = useWildCoin();
const acheterAmelioration = (type, price, name) => {
const prices = price;
const value = prices;
if (wildCoin >= value) {
if (type === "actif") {
setIncrementClick(incrementClick + incrementValue);
} else if (type === "passif") {
setIncrementPerSecond(incrementPerSecond + incrementValue);
}
setWildCoin(wildCoin - value);
switch (name) {
case "Tasse à café":
setCoffee((prevCoffee) => [true, prevCoffee[1] + 1]);
break;
case "Manic":
setManic((prevManic) => [true, prevManic[1] + 1]);
break;
case "Bonnet":
setBonnet((prevBonnet) => [true, prevBonnet[1] + 1]);
break;
case "Mr Bonhomme":
setSnowman((prevSnowman) => [true, prevSnowman[1] + 1]);
break;
case "Canne en sucre":
setSugar((prevSugar) => [true, prevSugar[1] + 1]);
break;
case "Cookie":
setCookie((prevCookie) => [true, prevCookie[1] + 1]);
break;
case "Couronne d'hiver":
setCouronne((prevCouronne) => [true, prevCouronne[1] + 1]);
break;
case "Mr pain d'épice":
setEpice((prevEpice) => [true, prevEpice[1] + 1]);
break;
case "Bière":
setBiere((prevBiere) => [true, prevBiere[1] + 1]);
setSantaDrunk(true);
break;
default:
break;
}
} else {
console.log("Pas assez de WildCoin pour acheter cette amélioration.");
}
};
return (
<div className="shopcardcontainer">
<div className="shopcontainer">
<div
className="cardpicture"
style={{ backgroundImage: `url(${image})` }}
alt={`image de ${name}`}
/>
<div>
<div className="titlesection">
<p className="itemname">{name}</p>
<div className="price">
<p className="itemprice">{price}</p>
<div className="priceicon" />
</div>
</div>
<div className="description">
<p className="itemdesc">
<em>
{type} + {incrementValue}
</em>
</p>
<p className="itemdesc">{description}</p>
</div>
</div>
<button
onClick={() => acheterAmelioration(type, price, name)}
className="primary-button"
>
Acheter
</button>
</div>
</div>
);
}

View File

@@ -0,0 +1,157 @@
import "../../scss/components/Hud.scss";
import { useWildCoin } from "../WildCoin/WildCoinContext";
import Timer from "../timer/Timer";
import propTypes from "prop-types";
function Hud({ isVisible }) {
Hud.propTypes = {
isVisible: propTypes.bool.isRequired,
};
const {
manic,
snowman,
bonnet,
sugar,
cookie,
couronne,
epice,
biere,
coffee,
} = useWildCoin();
const { incrementClick, incrementPerSecond } = useWildCoin();
const hiddenDiv = isVisible ? "none" : null;
return (
<div className="hudContainer">
<div style={{ display: hiddenDiv }} className="hudStats">
<div className="time section">
<p>Temps de jeu</p>
<p><Timer /></p>
</div>
<div className="auto section">
<p>Auto CPS</p>
<p>{incrementPerSecond}</p>
</div>
<div className="player section">
<p>Player Click</p>
<p>{incrementClick}</p>
</div>
</div>
<div className="hudBooster">
{coffee[0] === true ? (
<div className="boosterItem">
<div
className="boosterIcon"
style={{ backgroundImage: `url(/svg/Tasse.svg)` }}
alt="coffee"
/>
<div className="countbox">
<p className="boosterCount">{coffee[1]}</p>
</div>
</div>
) : null}
{manic[0] === true ? (
<div className="boosterItem">
<div
className="boosterIcon"
style={{ backgroundImage: `url(/svg/Hand.svg)` }}
alt="coffee"
/>
<div className="countbox">
<p className="boosterCount">{manic[1]}</p>
</div>
</div>
) : null}
{snowman[0] === true ? (
<div className="boosterItem">
<div
className="boosterIcon"
style={{ backgroundImage: `url(/svg/Bonhome.svg)` }}
alt="coffee"
/>
<div className="countbox">
<p className="boosterCount">{snowman[1]}</p>
</div>
</div>
) : null}
{bonnet[0] === true ? (
<div className="boosterItem">
<div
className="boosterIcon"
style={{ backgroundImage: `url(/svg/Bonnet.svg)` }}
alt="coffee"
/>
<div className="countbox">
<p className="boosterCount">{bonnet[1]}</p>
</div>
</div>
) : null}
{sugar[0] === true ? (
<div className="boosterItem">
<div
className="boosterIcon"
style={{ backgroundImage: `url(/svg/Canne.svg)` }}
alt="coffee"
/>
<div className="countbox">
<p className="boosterCount">{sugar[1]}</p>
</div>
</div>
) : null}
{cookie[0] === true ? (
<div className="boosterItem">
<div
className="boosterIcon"
style={{ backgroundImage: `url(/svg/Cookie.svg)` }}
alt="coffee"
/>
<div className="countbox">
<p className="boosterCount">{cookie[1]}</p>
</div>
</div>
) : null}
{couronne[0] === true ? (
<div className="boosterItem">
<div
className="boosterIcon"
style={{ backgroundImage: `url(/svg/Courone.svg)` }}
alt="coffee"
/>
<div className="countbox">
<p className="boosterCount">{couronne[1]}</p>
</div>
</div>
) : null}
{epice[0] === true ? (
<div className="boosterItem">
<div
className="boosterIcon"
style={{ backgroundImage: `url(/svg/PainDep.svg)` }}
alt="coffee"
/>
<div className="countbox">
<p className="boosterCount">{epice[1]}</p>
</div>
</div>
) : null}
{biere[0] === true ? (
<div className="boosterItem">
<div
className="boosterIcon"
style={{ backgroundImage: `url(/svg/Beer.svg)` }}
alt="coffee"
/>
<div className="countbox">
<p className="boosterCount">{biere[1]}</p>
</div>
</div>
) : null}
</div>
</div>
);
}
export default Hud;

View File

@@ -0,0 +1,75 @@
import { useWildCoin } from "./WildCoinContext";
function Ameliorations() {
const {
wildCoin,
incrementClick,
setWildCoin,
setIncrementClick,
incrementPerSecond,
setIncrementPerSecond,
} = useWildCoin();
const activePrices = [5, 15, 50, 500]; // prix
const passivePrices = [5, 15, 50, 500];
const activeIncrementValues = [1, 3, 10, 100]; // boost = incrementValue
const passiveIncrementValues = [1, 3, 10, 100]; // = incrementValue
const acheterAmelioration = (type, amount) => {
const prices = type === "actif" ? activePrices : passivePrices;
const incrementValues =
type === "actif" ? activeIncrementValues : passiveIncrementValues;
const price = prices[amount - 1];
const incrementValue = incrementValues[amount - 1];
if (wildCoin >= price) {
if (type === "actif") {
setIncrementClick(incrementClick + incrementValue);
} else if (type === "passif") {
setIncrementPerSecond(incrementPerSecond + incrementValue);
}
setWildCoin(wildCoin - price);
} else {
console.log("Pas assez de WildCoin pour acheter cette amélioration.");
}
};
return (
<div className="divMagasinAmelio">
<h2>Magasin d'Améliorations</h2>
<div className="divAmelioActives">
<p>Améliorations Actives :</p>
{[1, 2, 3, 4].map((amount) => (
<div key={amount}>
Price: {activePrices[amount - 1]} - (+
{activeIncrementValues[amount - 1]})
<button
className="amelioActives"
onClick={() => acheterAmelioration("actif", amount)}
>
Acheter
</button>
</div>
))}
</div>
<div className="divAmelioPassives">
<p>Améliorations Passives :</p>
{[1, 2, 3, 4].map((amount) => (
<div key={amount}>
Price: {passivePrices[amount - 1]} - (+
{passiveIncrementValues[amount - 1]})
<button
className="amelioPassives"
onClick={() => acheterAmelioration("passif", amount)}
>
Acheter
</button>
</div>
))}
</div>
</div>
);
}
export default Ameliorations;

View File

@@ -0,0 +1,43 @@
import { createContext, useContext, useState, useEffect } from "react";
export const WildCoinContext = createContext();
export const useWildCoin = () => {
return useContext(WildCoinContext);
};
export function WildCoinProvider({ children }) {
// Value of coin
const [wildCoin, setWildCoin] = useState(0);
// increment by click state
const [incrementClick, setIncrementClick] = useState(1);
// increment inner useEffect state
const [incrementPerSecond, setIncrementPerSecond] = useState(1);
const incrementWildCoin = (amount) => {
setWildCoin((prevWildCoin) => prevWildCoin + amount);
};
/**
* @passiveGenerationInterval incre per sec wild coin in wildCoin
* */
useEffect(() => {
const passiveGenerationInterval = setInterval(() => {
incrementWildCoin(incrementPerSecond);
}, 1000);
return () => clearInterval(passiveGenerationInterval);
}, [incrementPerSecond]);
const value = {
wildCoin,
setWildCoin,
incrementClick,
incrementWildCoin,
};
return (
<WildCoinContext.Provider value={value}>
{children}
</WildCoinContext.Provider>
);
}

View File

@@ -0,0 +1,138 @@
import { createContext, useContext, useState, useEffect } from "react";
export const WildCoinContext = createContext();
export const useWildCoin = () => {
return useContext(WildCoinContext);
};
export function WildCoinProvider({ children }) {
const initialState = {
wildCoin: 0,
incrementClick: 1,
incrementPerSecond: 0,
};
const [state, setState] = useState(() => {
const storedContext = JSON.parse(localStorage.getItem("wildCoinContext"));
return {
...initialState,
...(storedContext || {}),
};
});
const [coffee, setCoffee] = useState([false, 0]);
const [manic, setManic] = useState([false, 0]);
const [snowman, setSnowman] = useState([false, 0]);
const [bonnet, setBonnet] = useState([false, 0]);
const [sugar, setSugar] = useState([false, 0]);
const [cookie, setCookie] = useState([false, 0]);
const [couronne, setCouronne] = useState([false, 0]);
const [epice, setEpice] = useState([false, 0]);
const [biere, setBiere] = useState([false, 0]);
const [santaDrunk, setSantaDrunk] = useState(false);
const updateWildCoin = (amount) => {
setState((prev) => ({
...prev,
wildCoin: prev.wildCoin + amount,
}));
};
const incrementWildCoin = (amount) => {
updateWildCoin(amount);
};
const setIncrementClick = (amount) => {
setState((prev) => ({
...prev,
incrementClick: amount,
}));
};
const setIncrementPerSecond = (amount) => {
setState((prev) => ({
...prev,
incrementPerSecond: amount,
}));
};
const setWildCoin = (amount) => {
setState((prev) => ({
...prev,
wildCoin: amount,
}));
};
const [seconds, setSeconds] = useState(0);
useEffect(() => {
const intervalId = setInterval(() => {
setSeconds((prevSeconds) => prevSeconds + 1);
}, 1000);
return () => clearInterval(intervalId);
}, []);
const formatTime = (time) => {
const hours = Math.floor(time / 3600);
const minutes = Math.floor((time % 3600) / 60);
const seconds = time % 60;
const formattedTime = `${hours < 10 ? '0' : ''}${hours}:${minutes < 10 ? '0' : ''}${minutes}:${seconds < 10 ? '0' : ''}${seconds}`;
return formattedTime;
};
useEffect(() => {
localStorage.setItem("wildCoinContext", JSON.stringify(state));
}, [state]);
useEffect(() => {
const passiveGenerationInterval = setInterval(() => {
updateWildCoin(state.incrementPerSecond);
}, 1000);
return () => clearInterval(passiveGenerationInterval);
}, [state.incrementPerSecond]);
const contextValue = {
...state,
incrementWildCoin,
setIncrementClick,
setIncrementPerSecond,
setWildCoin,
coffee,
setCoffee,
manic,
setManic,
snowman,
setSnowman,
bonnet,
setBonnet,
sugar,
setSugar,
cookie,
setCookie,
couronne,
setCouronne,
epice,
setEpice,
biere,
setBiere,
setSantaDrunk,
santaDrunk,
seconds,
setSeconds,
formatTime,
};
return (
<WildCoinContext.Provider value={contextValue}>
{children}
</WildCoinContext.Provider>
);
}

View File

@@ -0,0 +1,16 @@
import { useWildCoin } from "./WildCoinContext";
import WildCoinS from "../../../public/WildCoin.svg";
function WildCoinIncrementAction() {
const { incrementClick, incrementWildCoin } = useWildCoin();
const handleIncrement = () => {
incrementWildCoin(incrementClick);
};
return (
<img src={WildCoinS} className="wildCoinBtn" style={{width:"40px", height:"40px"}} alt="Clique pour augmenter le score" aria-label="Clique pour augmenter le score" onClick={handleIncrement} />
);
}
export default WildCoinIncrementAction;

View File

@@ -0,0 +1,76 @@
import { NavLink as Link } from "react-router-dom";
import PropTypes from "prop-types";
import "../scss/components/navbar.scss";
import "../scss/root.scss";
import PrimaryButton from "./buttons/PrimaryButton";
export default function Burger({ navData }) {
return (
<nav className="menuToggle">
<input type="checkbox" aria-label="Menu" />
<span />
<span />
<span />
<ul className="menu">
{navData.map((navIndex) => {
if (navIndex.dropdown === undefined) {
return navIndex.btn === false ? (
<li key={navIndex.id}>
<Link className="mainLink" to={navIndex.linkurl}>
{navIndex.linkname}
</Link>
</li>
) : (
<li key={navIndex.id}>
<PrimaryButton
btnText={navIndex.linkname}
btnLink={navIndex.linkurl}
/>
</li>
);
}
return (
<li key={navIndex.id} className="dropdown">
<Link className="mainLink" to={navIndex.linkurl}>
{navIndex.linkname}
</Link>
<ul className="sousmenu">
{navIndex.dropdown.map((dropdown) => (
<li key={dropdown.id}>
<Link
className="dropLink"
to={navIndex.linkurl + dropdown.linkurl}
>
{dropdown.linkname}
</Link>
</li>
))}
</ul>
</li>
);
})}
</ul>
</nav>
);
}
Burger.propTypes = {
navData: PropTypes.arrayOf(
PropTypes.shape({
btn: PropTypes.bool,
id: PropTypes.string.isRequired,
linkname: PropTypes.string.isRequired,
linkurl: PropTypes.string.isRequired,
dropdown: PropTypes.arrayOf(
PropTypes.shape({
btn: PropTypes.bool,
id: PropTypes.string.isRequired,
linkname: PropTypes.string.isRequired,
linkurl: PropTypes.string.isRequired,
})
),
})
),
}.isRequired;

View File

@@ -0,0 +1,16 @@
import PropTypes from "prop-types";
import "../../scss/components/buttons.scss";
import { Link } from "react-router-dom";
export default function PrimaryButton({ btnText, btnLink }) {
PrimaryButton.propTypes = {
btnText: PropTypes.string.isRequired,
btnLink: PropTypes.string.isRequired,
};
return (
<Link className="primary-button" to={btnLink}>
{btnText}
</Link>
);
}

View File

@@ -0,0 +1,16 @@
import "../../scss/components/buttons.scss";
import PropTypes from "prop-types";
import { Link } from "react-router";
export default function SecondaryButton({ btnText, btnLink }) {
SecondaryButton.propTypes = {
btnText: PropTypes.string.isRequired,
btnLink: PropTypes.string.isRequired,
};
return (
<Link className="secondary-button" to={btnLink}>
{btnText}
</Link>
);
}

View File

@@ -0,0 +1,30 @@
import { Link } from "react-router-dom";
import PropTypes from "prop-types";
import "../../scss/components/CardContact.scss";
CardContact.propTypes = {
name: PropTypes.string.isRequired,
gitHub: PropTypes.string.isRequired,
};
function CardContact({ name, gitHub }) {
return (
<div className="cardContact">
<Link to={gitHub} target="_blank">
<button className="Btn">
<svg
className="svgIcon"
viewBox="0 0 496 512"
height="1.4em"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"></path>
</svg>
<span className="text">GitHub</span>
</button>
</Link>
<p>{name}</p>
</div>
);
}
export default CardContact;

View File

@@ -0,0 +1,84 @@
import "../scss/components/footer.scss";
import { NavLink as Link } from "react-router-dom";
import CardContact from "./cardsContact/CardContact";
const infoDev = [
{
id: "1",
name: "Alix C",
gitHub: "https://github.com/Halicksse",
},
{
id: "2",
name: "Sebatien L",
gitHub: "https://github.com/Lambseb",
},
{
id: "3",
name: "Baptiste S",
gitHub: "https://github.com/Batsave",
},
{
id: "4",
name: "Kevin T",
gitHub: "https://github.com/tetardtek",
},
{
id: "5",
name: "Nicolas DF",
gitHub: "https://github.com/Defreitasnicolas",
},
];
export default function Footer() {
return (
<footer className="footer">
<div className="footer-container">
<Link
to="/#home"
className="footer-logo"
alt="Logo"
aria-label="Logo Officiel"
title="Aller à la page d'accueil"
/>
<div className="section">
<p className="section-title">A Propos</p>
<p className="section-text">
Ce site est un prototype d'exercice développé lors d'un Hackathon
dans le cadre dune formation de Développeur Web et Mobile au sein
de la Wild Code School sur le campus Remote de Septembre 2023.
</p>
</div>
<div className="section">
<p className="section-title">Légale</p>
<ul className="section-list">
<li className="section-item">
<Link
to="/mentionslegales"
title="Aller à la page Mentions Légales"
>
Mentions Légales
</Link>
</li>
<li className="section-item">
<Link to="/cookies" title="Aller à la page Cookies">
Cookies
</Link>
</li>
<li className="section-item"></li>
</ul>
</div>
<div className="spacing" />
</div>
<div className="footer-section">
<div className="cardContactContainer">
{infoDev.map((info) => (
<CardContact key={info.id} name={info.name} gitHub={info.gitHub} />
))}
</div>
<p className="copyright">© 2023 | TrueQuiLeaks. Tous droits réservés.</p>
</div>
</footer>
);
}

View File

@@ -0,0 +1,146 @@
import { NavLink as Link } from "react-router-dom";
import PropTypes from "prop-types";
import "../scss/components/navbar.scss";
import "../scss/root.scss";
import PrimaryButton from "./buttons/PrimaryButton";
import Burger from "./burger";
import { useWildCoin } from "./WildCoin/WildCoinContext";
import HUDON from "../../public/NavBar/HUDON.svg";
import HUDOFF from "../../public/NavBar/HUDOFF.svg";
import SnowOn from "../../public/NavBar/SnowOn.svg";
import SnowOff from "../../public/NavBar/SnowOff.svg";
import { useState } from "react";
export default function Navbar({
navData,
isVisible,
setIsVisible,
toggleSnow,
setToggleSnow,
}) {
Navbar.propTypes = {
isVisible: PropTypes.bool,
setIsVisible: PropTypes.function,
setToggleSnow: PropTypes.function,
toggleSnow: PropTypes.bool,
}.isRequired;
const { wildCoin } = useWildCoin();
const [imageSrc, setImageSrc] = useState(HUDON);
const [snowImageSrc, setSnowImageSrc] = useState(SnowOff);
const [timerVisible, setTimerVisible] = useState(false);
const handleClickWildCoin = () => {
setTimerVisible(true);
};
const toggleHud = () => {
if (!isVisible) {
setIsVisible(true);
setImageSrc(HUDOFF);
} else {
setIsVisible(false);
setImageSrc(HUDON);
}
};
function toggleSnowBtn() {
if (toggleSnow === false) {
setToggleSnow(true);
setSnowImageSrc(SnowOn);
} else {
setToggleSnow(false);
setSnowImageSrc(SnowOff);
}
}
return (
<nav className="header-main">
<Link
className="logo"
to="/"
aria-label="Retourner à la page d'accueil"
title="Logo XmassClick"
/>
<div className="navbar">
<div className="wildCoin">
{new Intl.NumberFormat().format(wildCoin)}
</div>
<ul className="nav-list">
{navData.map((navIndex) => {
if (navIndex.dropdown === undefined) {
return navIndex.btn === false ? (
<li key={navIndex.id}>
<Link className="mainLink" to={navIndex.linkurl}>
{navIndex.linkname}
</Link>
</li>
) : (
<li key={navIndex.id}>
<PrimaryButton
btnText={navIndex.linkname}
btnLink={navIndex.linkurl}
/>
</li>
);
}
return (
<li key={navIndex.id} className="dropdown">
<Link className="mainLink" to={navIndex.linkurl}>
{navIndex.linkname}
</Link>
<ul className="dropdown-content">
{navIndex.dropdown.map((dropdown) => (
<li key={dropdown.id}>
<Link
className="dropLink"
to={navIndex.linkurl + dropdown.linkurl}
>
{dropdown.linkname}
</Link>
</li>
))}
</ul>
</li>
);
})}
</ul>
<img
onClick={() => toggleHud()}
src={imageSrc}
style={{ height: "28px" }}
alt="boutton on"
/>
<img
onClick={() => toggleSnowBtn()}
src={snowImageSrc}
style={{ height: "28px" }}
alt="boutton on"
/>
<Burger navData={navData} />
</div>
</nav>
);
}
Navbar.propTypes = {
navData: PropTypes.arrayOf(
PropTypes.shape({
btn: PropTypes.bool,
id: PropTypes.string,
linkname: PropTypes.string,
linkurl: PropTypes.string,
dropdown: PropTypes.arrayOf(
PropTypes.shape({
btn: PropTypes.bool,
id: PropTypes.string,
linkname: PropTypes.string,
linkurl: PropTypes.string,
})
),
})
),
};
Navbar.defaultProps = {
navData: [],
};

View File

@@ -0,0 +1,13 @@
import { useWildCoin } from "../WildCoin/WildCoinContext";
function Timer() {
const { formatTime, seconds } = useWildCoin();
return (
<div>
<p>{formatTime(seconds)}</p>
</div>
);
}
export default Timer;