5 changed files with 2469 additions and 111 deletions
@ -1,25 +0,0 @@
|
||||
import logo from './logo.svg'; |
||||
import './App.css'; |
||||
|
||||
function App() { |
||||
return ( |
||||
<div className="App"> |
||||
<header className="App-header"> |
||||
<img src={logo} className="App-logo" alt="logo" /> |
||||
<p> |
||||
Edit <code>src/App.js</code> and save to reload. |
||||
</p> |
||||
<a |
||||
className="App-link" |
||||
href="https://reactjs.org" |
||||
target="_blank" |
||||
rel="noopener noreferrer" |
||||
> |
||||
Learn React |
||||
</a> |
||||
</header> |
||||
</div> |
||||
); |
||||
} |
||||
|
||||
export default App; |
||||
@ -0,0 +1,48 @@
|
||||
import { useEffect, useRef, useState } from "react"; |
||||
|
||||
function useInterval(callback, delay) { |
||||
const savedCallback = useRef(); |
||||
|
||||
// Remember the latest callback.
|
||||
useEffect(() => { |
||||
savedCallback.current = callback; |
||||
}, [callback]); |
||||
|
||||
// Set up the interval.
|
||||
useEffect(() => { |
||||
function tick() { |
||||
savedCallback.current(); |
||||
} |
||||
if (delay !== null) { |
||||
let id = setInterval(tick, delay); |
||||
return () => clearInterval(id); |
||||
} |
||||
}, [delay]); |
||||
} |
||||
|
||||
|
||||
|
||||
function Countdown({ duration, onComplete }) { |
||||
// Initialize the countdown timer with the duration prop
|
||||
const [timeLeft, setTimeLeft] = useState(duration); |
||||
|
||||
// Decrement the timer by 1 second every 1000ms
|
||||
useInterval(() => { |
||||
if(timeLeft === 1) { |
||||
onComplete() |
||||
} else{ |
||||
|
||||
setTimeLeft(timeLeft - 1); |
||||
} |
||||
}, 1000); |
||||
|
||||
// Return the time left formatted as minutes and seconds
|
||||
let minutes = Math.floor(timeLeft / 60); |
||||
let seconds = timeLeft % 60; |
||||
return ( |
||||
<div>{seconds} |
||||
</div> |
||||
); |
||||
} |
||||
|
||||
export default Countdown |
||||
@ -1,17 +1,226 @@
|
||||
import React from 'react'; |
||||
import ReactDOM from 'react-dom/client'; |
||||
import './index.css'; |
||||
import App from './App'; |
||||
import reportWebVitals from './reportWebVitals'; |
||||
|
||||
const root = ReactDOM.createRoot(document.getElementById('root')); |
||||
root.render( |
||||
<React.StrictMode> |
||||
<App /> |
||||
</React.StrictMode> |
||||
); |
||||
import React, { useEffect, useState } from "react"; |
||||
import ReactDOM from "react-dom/client"; |
||||
import { BrowserRouter as Router, Routes, Route, Link } from "react-router-dom"; |
||||
import firebase from "firebase/app"; |
||||
import "firebase/database"; |
||||
import TextField from "@mui/material/TextField"; |
||||
import { Stack } from "@mui/system"; |
||||
import { Button } from "@mui/material"; |
||||
import { useForm } from "react-hook-form"; |
||||
import Countdown from "./Countdown"; |
||||
|
||||
import List from "@mui/material/List"; |
||||
import ListItem from "@mui/material/ListItem"; |
||||
import ListItemButton from "@mui/material/ListItemButton"; |
||||
import ListItemText from "@mui/material/ListItemText"; |
||||
import Checkbox from "@mui/material/Checkbox"; |
||||
|
||||
const MyForm = () => { |
||||
const [mandato, cambiaMandato] = useState(false); |
||||
const { register, handleSubmit } = useForm(); |
||||
const onSubmit = ({ testo, autore }) => { |
||||
var postListRef = firebase.database().ref("messaggi"); |
||||
var newPostRef = postListRef.push(); |
||||
console.log(newPostRef.key); |
||||
newPostRef.set({ |
||||
id: newPostRef.key, |
||||
autore, |
||||
testo, |
||||
timestamp: firebase.database.ServerValue.TIMESTAMP, |
||||
approvato: true, |
||||
}); |
||||
cambiaMandato(true); |
||||
}; |
||||
|
||||
if (mandato) { |
||||
return ( |
||||
<Stack> |
||||
<div>mandato e mo aspetti</div> |
||||
<Countdown onComplete={() => cambiaMandato(false)} duration={5} /> |
||||
</Stack> |
||||
); |
||||
} |
||||
return ( |
||||
<form onSubmit={handleSubmit(onSubmit)}> |
||||
<Stack spacing={2}> |
||||
<TextField |
||||
{...register("testo", { required: true, maxLength: 20 })} |
||||
id="outlined-basic" |
||||
label="messaggio" |
||||
variant="outlined" |
||||
/> |
||||
<TextField |
||||
{...register("autore", { pattern: /^[A-Za-z]+$/i })} |
||||
id="outlined-basic" |
||||
label="da" |
||||
variant="outlined" |
||||
/> |
||||
<Button type="submit" variant="contained"> |
||||
manda |
||||
</Button> |
||||
</Stack> |
||||
</form> |
||||
); |
||||
}; |
||||
|
||||
const firebaseConfig = { |
||||
apiKey: "AIzaSyASAEVOTQ38EmRoelz9qGiF6QsqpBOuU_k", |
||||
authDomain: "messaggi-letsswing.firebaseapp.com", |
||||
databaseURL: |
||||
"https://messaggi-letsswing-default-rtdb.europe-west1.firebasedatabase.app", |
||||
projectId: "messaggi-letsswing", |
||||
storageBucket: "messaggi-letsswing.appspot.com", |
||||
messagingSenderId: "154307951524", |
||||
appId: "1:154307951524:web:f320027fb89982a3f05f31", |
||||
}; |
||||
|
||||
firebase.initializeApp(firebaseConfig); |
||||
|
||||
function CheckboxListSecondary({ messaggi, onChecked }) { |
||||
return ( |
||||
<List |
||||
dense |
||||
sx={{ width: "100%", maxWidth: 360, bgcolor: "background.paper" }} |
||||
> |
||||
{messaggi.map((m) => { |
||||
const labelId = `checkbox-list-secondary-label-${m.timestamp}`; |
||||
return ( |
||||
<ListItem |
||||
key={m.timestamp} |
||||
secondaryAction={ |
||||
<Checkbox |
||||
edge="end" |
||||
onChange={() => onChecked(m)} |
||||
checked={m.approvato} |
||||
inputProps={{ "aria-labelledby": labelId }} |
||||
/> |
||||
} |
||||
disablePadding |
||||
> |
||||
<ListItemButton> |
||||
<ListItemText |
||||
id={labelId} |
||||
primary={`"${m.testo}" da ${m.autore}`} |
||||
/> |
||||
</ListItemButton> |
||||
</ListItem> |
||||
); |
||||
})} |
||||
</List> |
||||
); |
||||
} |
||||
|
||||
const Admin = () => { |
||||
const [messaggi, cambiaMessaggi] = useState([]); |
||||
const [indiceCorrente, cambiaindiceCorrente] = useState(0); |
||||
|
||||
useEffect(() => { |
||||
// Get a reference to the messages node in the Realtime Database
|
||||
var messagesRef = firebase.database().ref("/messaggi"); |
||||
|
||||
messagesRef.on("value", function (snapshot) { |
||||
var messaggi = snapshot.val(); |
||||
messaggi = Object.keys(messaggi).map((d) => messaggi[d]); |
||||
cambiaMessaggi(messaggi); |
||||
}); |
||||
|
||||
messagesRef.on("child_changed", function (snapshot) { |
||||
var messaggio = snapshot.val(); |
||||
const i = messaggi.findIndex((m) => messaggio.timestamp === m.timestamp); |
||||
}); |
||||
}, []); |
||||
|
||||
if (!messaggi.length) return <div>nessun messaggio</div>; |
||||
|
||||
return ( |
||||
<Stack> |
||||
<hr /> |
||||
<CheckboxListSecondary |
||||
messaggi={messaggi} |
||||
onChecked={(m) => { |
||||
firebase |
||||
.database() |
||||
.ref("messaggi/" + m.id) |
||||
.update({ |
||||
approvato: !m.approvato, |
||||
}); |
||||
}} |
||||
/> |
||||
</Stack> |
||||
); |
||||
}; |
||||
|
||||
// If you want to start measuring performance in your app, pass a function
|
||||
// to log results (for example: reportWebVitals(console.log))
|
||||
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
|
||||
reportWebVitals(); |
||||
const Proiezione = () => { |
||||
const [messaggi, cambiaMessaggi] = useState([]); |
||||
const [indiceCorrente, cambiaindiceCorrente] = useState(0); |
||||
|
||||
useEffect(() => { |
||||
// Get a reference to the messages node in the Realtime Database
|
||||
var messagesRef = firebase.database().ref("/messaggi"); |
||||
|
||||
messagesRef.on("child_added", function (snapshot) { |
||||
var messaggio = snapshot.val(); |
||||
cambiaMessaggi((oldArray) => |
||||
[...oldArray, messaggio].sort((a, b) => b.timestamp - a.timestamp) |
||||
); |
||||
}); |
||||
|
||||
messagesRef.on("child_changed", function (snapshot) { |
||||
var messaggio = snapshot.val(); |
||||
|
||||
cambiaMessaggi((oldArray) => { |
||||
var nuoviMessaggi = [...oldArray]; |
||||
var nuovoIndice = oldArray.findIndex((d) => d.id === messaggio.id); |
||||
if (nuovoIndice != -1) { |
||||
nuoviMessaggi[nuovoIndice] = messaggio; |
||||
} |
||||
return nuoviMessaggi; |
||||
}); |
||||
}); |
||||
}, []); |
||||
|
||||
const nextMessage = (i) => { |
||||
if(i === indiceCorrente) return |
||||
let nuovoIndice = (i + 1) % messaggi.length; |
||||
|
||||
if (!messaggi[nuovoIndice].approvato) { |
||||
nextMessage(nuovoIndice); |
||||
} else { |
||||
cambiaindiceCorrente(nuovoIndice) |
||||
} |
||||
}; |
||||
|
||||
const messaggioCorrente = messaggi[indiceCorrente]; |
||||
|
||||
return ( |
||||
<div> |
||||
<MyForm /> |
||||
{!messaggi.filter((m) => m.approvato).length && ( |
||||
<div>nessun messaggio</div> |
||||
)} |
||||
{messaggi.filter((m) => m.approvato).length && ( |
||||
<div> |
||||
<h1>{messaggioCorrente.testo}</h1> |
||||
<p>da {messaggioCorrente.autore}</p> |
||||
</div> |
||||
)} |
||||
<Button onClick={()=>nextMessage(indiceCorrente)}>next</Button> |
||||
|
||||
<Admin /> |
||||
</div> |
||||
); |
||||
}; |
||||
|
||||
const Input = () => { |
||||
return <div> Input </div>; |
||||
}; |
||||
|
||||
ReactDOM.createRoot(document.getElementById("root")).render( |
||||
<Router> |
||||
<Routes> |
||||
<Route path="/" element={<Input />} /> |
||||
<Route path="proiezione" element={<Proiezione />} /> |
||||
<Route path="admin" element={<Admin />} /> |
||||
</Routes> |
||||
</Router> |
||||
); |
||||
|
||||
Loading…
Reference in new issue