Add avatar image + generateur de pseudo

This commit is contained in:
Lucien Astié 2024-08-09 14:38:16 +02:00
parent ada0fa5ae8
commit 012caef506
7 changed files with 159 additions and 30 deletions

View file

@ -4,6 +4,7 @@ import { io } from "socket.io-client"
import { getRandomQuestion } from "./questions"
import { useForceUpdate } from "./forceUpdate"
import { IconCrown } from "@tabler/icons-react"
import { defaultAvatarImage } from '../avatarImage'
interface roomProps {
params: {
@ -17,6 +18,7 @@ export default function Home({ params }: roomProps) {
const [role, setRole] = useState("")
const [name, setName] = useState("")
const [avatar, setAvatar] = useState(defaultAvatarImage)
const [gameStarted, setGameStarted] = useState(false)
const [gameEnded, setGameEnded] = useState(false)
@ -37,14 +39,16 @@ export default function Home({ params }: roomProps) {
const roomNameDisplay = id.substring(0,3) + " " + id.substring(3,6)
useEffect(() => {
const username = localStorage.getItem('name')
setName(username)
const localName = localStorage.getItem('name')
setName(localName)
const localAvatar = localStorage.getItem('avatar')
setAvatar(localAvatar)
// Listen for incoming setMessages
socketRef.current = io("ws://localhost:3000");
socketRef.current.on("connect", () => {
setIsConnected(true)
socketRef.current.emit('room_connect', {"id": id, "name": username})
socketRef.current.emit('room_connect', {id: id, name: localName, avatar: localAvatar})
});
socketRef.current.on("new_player", (params) => {
@ -195,19 +199,21 @@ export default function Home({ params }: roomProps) {
}
{ (isConnected && players.length > 0) &&
<div className="flex flex-col space-y-16">
<div>
<div className="grid grid-cols-3 gap-4">
{ players.map((player) => {
console.log(player)
if(player.role == "player") {
return (
<p>{player.name}</p>
)
}
if(player.role == "owner") {
return (
<p className="flex flex-row">{player.name}<IconCrown /></p>
)
}
return (
<>
<div className="flex flex-col items-center">
<div className="avatar indicator">
{player.role == "owner" && <IconCrown className="indicator-item" />}
<div className="w-16 rounded">
<img src={player.avatar} />
</div>
</div>
<p className="flex flex-row">{player.name}</p>
</div>
</>
)
})}
</div>
{ role == "owner" &&

1
app/avatarImage.ts Normal file

File diff suppressed because one or more lines are too long

View file

@ -2,10 +2,16 @@
import { navigate } from './action'
import { useState, useEffect, useRef } from 'react'
import { IconPencilMinus } from "@tabler/icons-react"
import { IconPencilMinus, IconCamera, IconDice6 } from "@tabler/icons-react"
import { defaultAvatarImage } from './avatarImage'
import { getUsername } from './usernameGenerate'
import Webcam from 'react-webcam'
export default function Home() {
const [name, setName] = useState("")
const [avatar, setAvatar] = useState(defaultAvatarImage)
const [showWebcam, setShowWebcam] = useState(false)
const webcamRef = useRef()
const modal = useRef()
const inputName = useRef()
@ -14,35 +20,113 @@ export default function Home() {
localStorage.setItem("name", inputName.current.value)
}
function setAndStoreAvatar(data){
resizeBase64Image(data).then((data) => {
localStorage.setItem("avatar", data)
setAvatar(data)
})
}
function takePictureAvatar() {
const imageSrc = webcamRef.current.getScreenshot()
setAndStoreAvatar(imageSrc)
setShowWebcam(false)
}
function getBase64OfImage(file, cb) {
let reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function () {
cb(reader.result)
};
reader.onerror = function (error) {
console.log('Error: ', error);
};
}
function resizeBase64Image(base64Image) {
return new Promise((resolve, reject) => {
const maxSizeInKB = 500;
const maxSizeInBytes = maxSizeInKB * 1024;
const img = new Image();
img.src = base64Image;
img.onload = function () {
const canvas = document.createElement("canvas");
const ctx = canvas.getContext('2d');
const width = img.width;
const height = img.height;
const aspectRatio = width / height;
const newWidth = Math.sqrt(maxSizeInBytes * aspectRatio);
const newHeight = Math.sqrt(maxSizeInBytes / aspectRatio);
canvas.width = newWidth;
canvas.height = newHeight;
ctx.drawImage(img, 0, 0, newWidth, newHeight);
let quality = 0.8;
let dataURL = canvas.toDataURL('image/jpeg', quality);
resolve(dataURL);
};
});
}
useEffect(() => {
let localName = localStorage.getItem("name")
let localAvatar = localStorage.getItem("avatar")
if(localName != null){
setName(localName)
} else {
modal.current.showModal()
}
if(localAvatar != null) {
setAvatar(localAvatar)
}
}, [])
return (
<main data-theme="light" className="flex min-h-screen flex-col items-center space-y-16 p-24">
<dialog ref={modal} className="modal">
<div className="modal-box">
<label className="form-control w-full max-w-xs">
<div className="modal-box flex flex-col space-y-4">
<div className="avatar flex flex-col items-center space-y-4">
<div className="w-24 rounded">
<img src={avatar} />
</div>
{ showWebcam &&
<>
<Webcam ref={webcamRef} />
<button className="btn btn-primary" onClick={takePictureAvatar}><IconCamera /></button>
</>
}
{ !showWebcam &&
<>
<button className="btn btn-primary" onClick={() => {setShowWebcam(true)}}>Use Webcam</button>
<input type="file" onChange={(e) => {getBase64OfImage(e.target.files[0], (data) => setAndStoreAvatar(data))}} className="file-input w-full max-w-xs"/>
</>
}
</div>
<label className="form-control w-full">
<div className="label">
<span className="label-text">What is your name?</span>
</div>
<input type="text" ref={inputName} defaultValue={name} placeholder="Name" className="input input-bordered w-full max-w-xs" />
<div className="flex flex-row w-full space-x-4">
<input type="text" ref={inputName} defaultValue={name} placeholder="Name" className="input input-bordered w-full" />
<button onClick={() => {inputName.current.value = getUsername()}} ><IconDice6 /></button>
</div>
</label>
<div className="modal-action">
<form method="dialog">
{/* if there is a button in form, it will close the modal */}
<button onClick={setUsername} className="btn">Close</button>
<button onClick={setUsername} className="btn">Save</button>
</form>
</div>
</div>
</dialog>
<h1 className="text-3xl">Bazaar</h1>
<div className="flex flex-col space-y-4 items-center">
<div className="avatar">
<div className="w-24 rounded">
<img src={avatar} />
</div>
</div>
<div className="flex flex-row space-x-4">
<span className="text-xl">{name}</span>
<button onClick={() => { modal.current.showModal()}}>

25
app/usernameGenerate.ts Normal file
View file

@ -0,0 +1,25 @@
const prenom = [
"Stéphane",
"Hubert",
"Alphonse",
"Marjolaine",
"Cathy",
"Patrick",
"Agathe",
"Erneste",
]
const nom = [
"Falzar",
"Globule",
"Bermuda",
"Zigounette",
"Pissenlit",
"Détritus",
]
export function getUsername(){
const prenomIndex = Math.floor(Math.random() * prenom.length)
const nomIndex = Math.floor(Math.random() * nom.length)
return prenom[prenomIndex] + " " + nom[nomIndex]
}