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
+1 -11
View File
@@ -26,18 +26,8 @@
-->
<title>React App</title>
</head>
<body>
<body style="margin: 0">
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
+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>