added image upload functionality

This commit is contained in:
Danilo Di Cuia
2022-12-27 15:11:17 +01:00
parent b4cfaaddf1
commit 2b562e3495
7 changed files with 242 additions and 189 deletions
+52
View File
@@ -0,0 +1,52 @@
import React, { useEffect, useState } from "react";
import firebase from "firebase/app";
import { Stack } from "@mui/system";
import { CheckboxListSecondary } from "./index";
export const Admin = () => {
const [messaggi, cambiaMessaggi] = useState([]);
useEffect(() => {
// Get a reference to the messages node in the Realtime Database
var messagesRef = firebase.database().ref("/messaggi");
console.log(messagesRef);
messagesRef.on("value", function (snapshot) {
var messaggi = snapshot.val();
console.log(messaggi);
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);
});
}, []);
let element;
if (!messaggi.length) {
element = <div>nessun messaggio</div>;
} else {
element = (
<CheckboxListSecondary
messaggi={messaggi}
onChecked={(m) => {
firebase
.database()
.ref("messaggi/" + m.id)
.update({
approvato: !m.approvato,
});
}}
/>
);
}
return (
<Stack>
<h2>Admin</h2>
{element}
</Stack>
);
};
-38
View File
@@ -1,38 +0,0 @@
.App {
text-align: center;
}
.App-logo {
height: 40vmin;
pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
+64 -22
View File
@@ -1,9 +1,15 @@
import React, { useState } from "react";
import { storage, firestore } from "firebase/app";
import firebase from "firebase/app";
import "firebase/storage";
import "firebase/firestore";
import { Stack } from "@mui/system";
function ImageUpload() {
const IDLE = 0;
const IMAGE_SET = 1;
const UPLOADING = 2;
const DONE = 3;
function ImageUpload({ onImageURLSet }) {
const [state, setState] = useState();
const [image, setImage] = useState(null);
const [imageUrl, setImageUrl] = useState("");
const [progress, setProgress] = useState(0);
@@ -11,11 +17,17 @@ function ImageUpload() {
const handleChange = (e) => {
if (e.target.files[0]) {
setImage(e.target.files[0]);
setState(1);
}
};
const handleUpload = () => {
const uploadTask = storage.ref(`images/${image.name}`).put(image);
const uploadTask = firebase
.storage()
.ref(`images/${image.name}`)
.put(image);
setState(2);
uploadTask.on(
"state_changed",
@@ -29,34 +41,64 @@ function ImageUpload() {
console.log(error);
},
() => {
storage
firebase
.storage()
.ref("images")
.child(image.name)
.getDownloadURL()
.then((url) => {
setImageUrl(url);
firestore()
.collection("images")
.add({
imageUrl,
createdAt: new Date(),
})
.then(() => {
setProgress(0);
setImage(null);
});
setProgress(0);
setImage(null);
onImageURLSet(url);
setState(3);
});
}
);
};
return (
<div>
<input type="file" onChange={handleChange} />
<button onClick={handleUpload}>Upload</button>
<progress value={progress} max="100" />
</div>
);
let componente;
switch (state) {
default:
case IDLE:
componente = <input type="file" onChange={handleChange} />;
break;
case IMAGE_SET:
componente = (
<Stack>
<img style={{ width: 200 }} src={URL.createObjectURL(image)} />
<Stack spacing={2} direction="row">
<button
onClick={() => {
setState(IDLE);
}}
>
annulla
</button>
<button onClick={handleUpload}>carica</button>
</Stack>
</Stack>
);
break;
case UPLOADING:
componente = (
<div>
<img style={{ width: 200 }} src={image.src} />
<progress value={progress} max="100" />
</div>
);
break;
case DONE:
componente = (
<div>
<img style={{ width: 200 }} src={imageUrl} />
</div>
);
}
return <Stack>{componente}</Stack>;
}
export default ImageUpload;
+65
View File
@@ -0,0 +1,65 @@
import React, { useState } from "react";
import firebase from "firebase/app";
import TextField from "@mui/material/TextField";
import { Container, Stack } from "@mui/system";
import { Button } from "@mui/material";
import { useForm } from "react-hook-form";
import Countdown from "./Countdown";
import ImageUpload from "./ImageUpload";
export const MyForm = () => {
const [mandato, cambiaMandato] = useState(false);
const [immagineURL, cambiaimmagineURL] = useState(null);
const { register, handleSubmit } = useForm();
const onSubmit = ({ testo, autore }) => {
cambiaMandato(true);
var postListRef = firebase.database().ref("messaggi");
var newPostRef = postListRef.push();
const update = {
id: newPostRef.key,
autore,
testo,
timestamp: firebase.database.ServerValue.TIMESTAMP,
approvato: true,
};
if (immagineURL) update.immagineURL = immagineURL;
newPostRef.set(update);
};
const onImageURLSet = (url) => {
cambiaimmagineURL(url);
};
if (mandato) {
return (
<Stack>
<div>mandato e mo aspetti</div>
<Countdown onComplete={() => cambiaMandato(false)} duration={5} />
</Stack>
);
}
return (
<Container maxWidth="sm" style={{ marginTop: 100 }}>
<form onSubmit={handleSubmit(onSubmit)}>
<Stack spacing={2}>
<ImageUpload onImageURLSet={onImageURLSet} />
<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>
</Container>
);
};
+48 -11
View File
@@ -1,9 +1,12 @@
import React, { useEffect, useState } from "react";
import firebase from "firebase/app";
import { Button } from "@mui/material";
import { MyForm, Admin } from "./index";
import { Button, Grid } from "@mui/material";
import { Admin } from "./Admin";
import { MyForm } from "./MyForm";
import { useInterval } from "./Countdown";
window.debug = false;
export const Proiezione = () => {
const [messaggi, cambiaMessaggi] = useState([]);
const [messaggiApprovati, cambiaMessaggiApprovati] = useState([]);
@@ -14,6 +17,7 @@ export const Proiezione = () => {
messagesRef.on("child_added", function (snapshot) {
var messaggio = snapshot.val();
console.log(messaggio);
cambiaMessaggi((oldArray) => {
const newArray = [...oldArray, messaggio].sort(
(a, b) => b.timestamp - a.timestamp
@@ -44,7 +48,7 @@ export const Proiezione = () => {
const ContainerMessaggio = () => {
if (!messaggiApprovati.length) {
<div>nessun messaggio</div>;
return <div>nessun messaggio</div>;
} else {
const messaggioCorrente = messaggiApprovati[indiceCorrente];
@@ -59,17 +63,43 @@ export const Proiezione = () => {
return (
<div>
<MyForm />
<ContainerMessaggio />
<Admin />
<Grid
style={{
width: "100%",
height: "100vh",
background: "black",
fontFamily: "sans-serif",
fontWeight: "bold",
color: "white",
display: "flex",
justifyContent: "space-around",
alignContent: "center",
alignItems: "center",
textAlign: "center",
}}
>
<ContainerMessaggio />
</Grid>
</div>
);
};
const Immagine = ({ url }) => {
return (
<div
style={{
height: 400,
width: 400,
borderRadius: "50%",
backgroundSize: "cover",
backgroundImage: `url("${url}")`,
backgroundPositionX: "center",
}}
></div>
);
};
const Messaggio = ({ nextMessage, messaggioCorrente }) => {
const [timeLeft, setTimeLeft] = useState(5);
// Decrement the timer by 1 second every 1000ms
useInterval(() => {
if (timeLeft === 1) {
nextMessage();
@@ -78,13 +108,20 @@ const Messaggio = ({ nextMessage, messaggioCorrente }) => {
}
}, 1000);
console.log("asdf");
return (
<div>
{messaggioCorrente.immagineURL && (
<Immagine url={messaggioCorrente.immagineURL} />
)}
<h1>{messaggioCorrente.testo}</h1>
<p>da {messaggioCorrente.autore}</p>
<Button onClick={() => nextMessage()}>next</Button>
{timeLeft}
{debug && (
<div>
<Button onClick={() => nextMessage()}>next</Button>
{timeLeft}
</div>
)}
</div>
);
};
+12 -107
View File
@@ -1,13 +1,8 @@
import React, { useEffect, useState } from "react";
import React 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";
@@ -15,69 +10,23 @@ import ListItemButton from "@mui/material/ListItemButton";
import ListItemText from "@mui/material/ListItemText";
import Checkbox from "@mui/material/Checkbox";
import { Proiezione } from "./Proiezione";
export 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>
);
};
import { MyForm } from "./MyForm";
import { Admin } from "./Admin";
const firebaseConfig = {
apiKey: "AIzaSyASAEVOTQ38EmRoelz9qGiF6QsqpBOuU_k",
authDomain: "messaggi-letsswing.firebaseapp.com",
apiKey: "AIzaSyBWE1l8WV_7eyKT-PMu0Kq2w_WiV0SUhJw",
authDomain: "messaggiswing.firebaseapp.com",
projectId: "messaggiswing",
storageBucket: "messaggiswing.appspot.com",
messagingSenderId: "983131964310",
appId: "1:983131964310:web:5ef430e42c42d2dfe253b7",
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",
"https://messaggiswing-default-rtdb.europe-west1.firebasedatabase.app",
};
firebase.initializeApp(firebaseConfig);
function CheckboxListSecondary({ messaggi, onChecked }) {
export function CheckboxListSecondary({ messaggi, onChecked }) {
return (
<List
dense
@@ -111,54 +60,10 @@ function CheckboxListSecondary({ messaggi, onChecked }) {
);
}
export 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>
);
};
const Input = () => {
return <div> Input </div>;
};
ReactDOM.createRoot(document.getElementById("root")).render(
<Router>
<Routes>
<Route path="/" element={<Input />} />
<Route path="/" element={<MyForm />} />
<Route path="proiezione" element={<Proiezione />} />
<Route path="admin" element={<Admin />} />
</Routes>