Skip to content

Commit

Permalink
Merge pull request #18 from davidvicentecode/dev
Browse files Browse the repository at this point in the history
Game mechanics and ui design
  • Loading branch information
david-vct authored Mar 31, 2024
2 parents bc6979e + ee7bab7 commit a0a5f7b
Show file tree
Hide file tree
Showing 27 changed files with 1,590 additions and 216 deletions.
996 changes: 985 additions & 11 deletions package-lock.json

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,20 @@
"zod": "^3.22.4"
},
"devDependencies": {
"@tailwindcss/typography": "^0.5.12",
"@types/lodash": "^4.17.0",
"@types/react": "^18.2.66",
"@types/react-dom": "^18.2.22",
"@typescript-eslint/eslint-plugin": "^7.2.0",
"@typescript-eslint/parser": "^7.2.0",
"@vitejs/plugin-react": "^4.2.1",
"autoprefixer": "^10.4.19",
"daisyui": "^4.9.0",
"eslint": "^8.57.0",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.6",
"postcss": "^8.4.38",
"tailwindcss": "^3.4.3",
"typescript": "^5.2.2",
"vite": "^5.2.0"
}
Expand Down
6 changes: 6 additions & 0 deletions postcss.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
2 changes: 2 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ import { QuestionCreator } from "./pages/QuestionCreator/QuestionCreator"
import { GameController } from "./pages/game/GameController"
import { Oups } from "./pages/Oups"
import { TestsPage } from "./pages/TestsPage"
import { Navbar } from "./components/Navbar"

function App() {
return (
<div className="App">
<Router>
<Navbar />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/signin" element={<Auth />} />
Expand Down
21 changes: 14 additions & 7 deletions src/components/JoinGame.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,23 @@ export const JoinGame = () => {
}

return (
<div>
<div className="flex flex-col space-y-4">
<div>
<input
placeholder="Code"
onChange={(e) => setJoinGamemId(e.target.value)}
/>
<button onClick={joinGameHandler}>Rejoindre partie</button>
<div className="join">
<input
className="input input-bordered rounded-full join-item"
placeholder="Code"
onChange={(e) => setJoinGamemId(e.target.value)}
/>
<button className="btn btn-primary rounded-r-full join-item" onClick={joinGameHandler}>
Rejoindre partie
</button>
</div>
</div>
<div>
<button onClick={newGameHandler}>Nouvelle partie</button>
<button className="btn btn-secondary rounded-full" onClick={newGameHandler}>
Nouvelle partie
</button>
</div>
</div>
)
Expand Down
23 changes: 19 additions & 4 deletions src/components/Navbar.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,26 @@
import { Link } from "react-router-dom"
import { ThemeSwitch } from "./ThemeSwitch"

export const Navbar = () => {
return (
<div>
<Link to={"/"}>Home</Link>
<Link to={"/questions"}>Créer des questions</Link>
<Link to={"/signin"}>Connexion</Link>
<div className="navbar bg-base-100 fixed top-0 px-4">
<div className="navbar-start space-x-4">
<div className="menu menu-vertical lg:menu-horizontal bg-base-100 rounded-box">
<li>
<Link to={"/"}>Home</Link>
</li>
<li>
<Link to={"/questions"}>Créer des questions</Link>
</li>
<li>
<Link to={"/signin"}>Connexion</Link>
</li>
</div>
</div>

<div className="navbar-end">
<ThemeSwitch />
</div>
</div>
)
}
40 changes: 40 additions & 0 deletions src/components/ThemeSwitch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { useEffect, useState } from "react"

enum Theme {
LIGHT = "emerald",
DARK = "dracula",
}

export const ThemeSwitch = () => {
const [theme, setTheme] = useState(localStorage.getItem("theme") ?? Theme.DARK)

useEffect(() => {
localStorage.setItem("theme", theme)
document.querySelector("html")?.setAttribute("data-theme", theme)
}, [theme])

const handleThemeSwitch = (e: React.ChangeEvent<HTMLInputElement>) => {
if (e.target.checked) {
setTheme(Theme.DARK)
} else {
setTheme(Theme.LIGHT)
}
}

return (
<label className="swap swap-rotate">
{/* this hidden checkbox controls the state */}
<input type="checkbox" className="theme-controller" checked={theme === Theme.DARK} onChange={handleThemeSwitch} />

{/* sun icon */}
<svg className="swap-off fill-current w-8 h-8" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M5.64,17l-.71.71a1,1,0,0,0,0,1.41,1,1,0,0,0,1.41,0l.71-.71A1,1,0,0,0,5.64,17ZM5,12a1,1,0,0,0-1-1H3a1,1,0,0,0,0,2H4A1,1,0,0,0,5,12Zm7-7a1,1,0,0,0,1-1V3a1,1,0,0,0-2,0V4A1,1,0,0,0,12,5ZM5.64,7.05a1,1,0,0,0,.7.29,1,1,0,0,0,.71-.29,1,1,0,0,0,0-1.41l-.71-.71A1,1,0,0,0,4.93,6.34Zm12,.29a1,1,0,0,0,.7-.29l.71-.71a1,1,0,1,0-1.41-1.41L17,5.64a1,1,0,0,0,0,1.41A1,1,0,0,0,17.66,7.34ZM21,11H20a1,1,0,0,0,0,2h1a1,1,0,0,0,0-2Zm-9,8a1,1,0,0,0-1,1v1a1,1,0,0,0,2,0V20A1,1,0,0,0,12,19ZM18.36,17A1,1,0,0,0,17,18.36l.71.71a1,1,0,0,0,1.41,0,1,1,0,0,0,0-1.41ZM12,6.5A5.5,5.5,0,1,0,17.5,12,5.51,5.51,0,0,0,12,6.5Zm0,9A3.5,3.5,0,1,1,15.5,12,3.5,3.5,0,0,1,12,15.5Z" />
</svg>

{/* moon icon */}
<svg className="swap-on fill-current w-8 h-8" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M21.64,13a1,1,0,0,0-1.05-.14,8.05,8.05,0,0,1-3.37.73A8.15,8.15,0,0,1,9.08,5.49a8.59,8.59,0,0,1,.25-2A1,1,0,0,0,8,2.36,10.14,10.14,0,1,0,22,14.05,1,1,0,0,0,21.64,13Zm-9.5,6.69A8.14,8.14,0,0,1,7.08,5.22v.27A10.15,10.15,0,0,0,17.22,15.63a9.79,9.79,0,0,0,2.1-.22A8.11,8.11,0,0,1,12.14,19.73Z" />
</svg>
</label>
)
}
21 changes: 21 additions & 0 deletions src/components/question/AnswerReview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
type AnswerReviewProps = {
username: string
answer: string
sendIsRightAnswer: (isRight: boolean) => void
}

export const AnswerReview = (props: AnswerReviewProps) => {
return (
<div className="grid grid-cols-4 gap-4">
<div className="col-span-3 align-middle self-center">{props.username + " : " + props.answer}</div>
<div className="join join-horizontal rounded-full grow-0">
<button className="btn btn-error join-item text-2xl" onClick={() => props.sendIsRightAnswer(false)}>
💩
</button>
<button className="btn btn-success join-item text-2xl" onClick={() => props.sendIsRightAnswer(true)}>
🥳
</button>
</div>
</div>
)
}
25 changes: 25 additions & 0 deletions src/components/question/QuestionView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Question } from "../../utils/types"

type QuestionViewProps = {
question: Question
isAnswerVisible?: boolean
}

export const QuestionView = ({ question, isAnswerVisible = true }: QuestionViewProps) => {
return (
<div className="flex flex-col space-y-4">
<h2 className="text-2xl">{question.title}</h2>
<div className="space-x-2">
{question.tags.map((tag) => (
<span className="badge badge-outline cursor-default">{tag}</span>
))}
</div>
<div className="">
{question.body.map((text) => (
<div>{text}</div>
))}
</div>
{isAnswerVisible && <div>{question.answers.map((answer, index) => (index === 0 ? answer : ", " + answer))}</div>}
</div>
)
}
3 changes: 3 additions & 0 deletions src/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
1 change: 1 addition & 0 deletions src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from "react"
import ReactDOM from "react-dom/client"
import App from "./App.tsx"
import "./index.css"

ReactDOM.createRoot(document.getElementById("root")!).render(
<React.StrictMode>
Expand Down
75 changes: 50 additions & 25 deletions src/pages/Auth.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,62 @@
import { useEffect, useState } from "react"
import {
getUserInfo,
logout,
signIn,
signInWithGoogle,
} from "../services/authentication"
import { useState } from "react"
import { logout, signIn, signInWithGoogle } from "../services/authentication"
import { Navbar } from "../components/Navbar"

export const Auth = () => {
const [email, setEmail] = useState("")
const [password, setPassword] = useState("")
const [username, setUsername] = useState("")

useEffect(() => {
const userInfo = getUserInfo()
setUsername(userInfo.name)
}, [])

return (
<div>
<div className="hero min-h-screen bg-base-200">
<Navbar />
<div>
<input placeholder="Email" onChange={(e) => setEmail(e.target.value)} />
<input
placeholder="Password"
type="password"
onChange={(e) => setPassword(e.target.value)}
/>
<button onClick={() => signIn(email, password)}>Sign In</button>
<button onClick={signInWithGoogle}>Sign in with Google</button>
<button onClick={logout}>Logout</button>
<div className="hero-content flex-col lg:flex-row-reverse">
<div className="card shrink-0 w-full max-w-sm shadow-2xl bg-base-100">
<div className="card-body">
<div className="form-control">
<label className="label">
<span className="label-text">Email</span>
</label>
<input
type="email"
className="input input-bordered"
placeholder="email"
onChange={(e) => setEmail(e.target.value)}
/>
</div>
<div className="form-control">
<label className="label">
<span className="label-text">Password</span>
</label>
<input
className="input input-bordered"
placeholder="password"
type="password"
onChange={(e) => setPassword(e.target.value)}
/>
</div>
<div className="form-control mt-6">
<button className="btn btn-neutral" onClick={() => signIn(email, password)}>
Sign In
</button>
</div>

<div className="divider">ou</div>

<button className="btn btn-primary" onClick={signInWithGoogle}>
Sign in with Google
</button>

<div className="mt-6">
Assez pour aujourd'hui...&nbsp;
<span>
<a className="link" onClick={logout}>
logout
</a>
</span>
</div>
</div>
</div>
</div>
<div>Hello {username}!</div>
</div>
)
}
14 changes: 8 additions & 6 deletions src/pages/Home.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { JoinGame } from "../components/JoinGame"
import { Navbar } from "../components/Navbar"

export const Home = () => {
return (
<div>
<Navbar />
<h1>Rculture</h1>
<p>A game about culture, quiz and chill</p>
<JoinGame />
<div className="hero min-h-screen bg-base-200">
<div className="hero-content text-center">
<div className="max-w-md">
<h1 className="text-5xl font-bold">Rculture</h1>
<p className="py-6">A game about culture, quiz and chill</p>
<JoinGame />
</div>
</div>
</div>
)
}
24 changes: 4 additions & 20 deletions src/pages/QuestionCreator/QuestionCreator.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,11 @@
import { useState } from "react"
import { QuestionType } from "../../utils/types"
import { CompleteQuestionCreator } from "./CompleteQuestionCreator"
import { SimpleQuestionCreator } from "./SimpleQuestionCreator"
import { ChoiceQuestionCreator } from "./ChoiceQuestionCreator"
import { Navbar } from "../../components/Navbar"

export const QuestionCreator = () => {
const [questionType, setQuestionType] = useState(0)

return (
<div>
<Navbar />
<h1>Créateur de questions</h1>
<div>
<select onChange={(e) => setQuestionType(+e.target.value)}>
<option value={QuestionType.SIMPLE}>Question simple</option>
<option value={QuestionType.COMPLETE}>Question complete</option>
<option value={QuestionType.CHOICE}>Question à choix</option>
</select>

{questionType == QuestionType.SIMPLE && <SimpleQuestionCreator />}
{questionType == QuestionType.COMPLETE && <CompleteQuestionCreator />}
{questionType == QuestionType.CHOICE && <ChoiceQuestionCreator />}
<div className="min-h-screen bg-base-200 flex flex-col justify-center items-center">
<div className="p-8 rounded-box w-1/3 max-w-2xl">
<h1 className="text-5xl font-bold pb-16">Créateur de questions</h1>
<SimpleQuestionCreator />
</div>
</div>
)
Expand Down
13 changes: 8 additions & 5 deletions src/pages/QuestionCreator/SimpleQuestionCreator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,14 @@ export const SimpleQuestionCreator = () => {
}

return (
<div>
<input placeholder="Question" onChange={(e) => setTitle(e.target.value)} />
<input placeholder="Réponses" onChange={(e) => setAnswers(e.target.value)} />
<input placeholder="Tags" onChange={(e) => setTags(e.target.value)} />
<button onClick={createQuestionHandler}>Créer</button>
<div className="flex flex-col space-y-4">
<input className="input input-bordered" placeholder="Question" onChange={(e) => setTitle(e.target.value)} />
<textarea className="textarea textarea-bordered" placeholder="Déscription"></textarea>
<input className="input input-bordered" placeholder="Réponses" onChange={(e) => setAnswers(e.target.value)} />
<input className="input input-bordered" placeholder="Tags" onChange={(e) => setTags(e.target.value)} />
<button className="btn btn-primary rounded-full" onClick={createQuestionHandler}>
Créer
</button>
</div>
)
}
Loading

0 comments on commit a0a5f7b

Please sign in to comment.