added image upload functionality
This commit is contained in:
+1
-11
@@ -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>
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user