Compare commits

4 Commits

Author SHA1 Message Date
bbed8c7de1 Update 'README.md' 2022-10-04 16:07:30 +02:00
380b251cc1 Update 'README.md' 2022-10-04 16:03:17 +02:00
53a7c652aa Update 'README.md' 2022-10-04 16:02:45 +02:00
3a26a88114 Modo più semplice per creare il json così da debuggarlo meglio
Dalla riga 90 alla 112, metodo più standard per creare il json (il problema "TypeError: string indices must be integers" sulla serialization di Django c'è ugualmente, ma così il codice è più pulito)
2022-10-04 11:44:40 +02:00
7 changed files with 233 additions and 530 deletions

5
LICENSE Normal file
View File

@@ -0,0 +1,5 @@
Copyright (C) YEAR by AUTHOR EMAIL
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

147
README.md
View File

@@ -1,49 +1,114 @@
## SCRAPE JUST EAT
# CENANDOODLE
Scarica liberamente tutti i dati e il menu di un ristorante presente su JustEat
||| Ordinare cibo con doodle in rete locale o anche no |||
## Dati raccolti:
- `Prodotti:`
- `Nome`
- `Descrizione`
- `Numero dei pezzi`
- `Prezzo`
- `Ristorante:`
- `Nome`
- `Via`
- `Numero di telefono`
- `Disponibilità consegna`
- `Disponiilità ritiro al ristorante`
- `Costo consegna`
- `Ordine minimo`
||| Doodle condiviso su rete locale per ordinare e organizzare cibo e bevande (se previste) |||
-----------------------------------
setup-sh -> installa requisiti (tutti pip3 tra cui jawanndenn)
## INSTALLAZIONE
scrapeJE.py -> scrapa e stora dentro a 4 liste il nome prodotto, la descrizione, il numero dei pezzi(es 5 falefel per x€) e il prezzo. Infine crea jwndn.json che è un formattato leggibile da jawanndenn con il nome del ristorante e il nome dei prodotti.
Scarica il git
```bash
#Scarica il git
git clone https://repo.esiliati.org/scossa/scrapeje.git
#Entra nella cartella di scrapeje
cd scrapeje
```
start.sh -> avvia scrapeJE.py e poi cerca di usare (in vano, nel senso che nonfunziona) la funzione di javanndenn che carica un file json
----------------------------------------
# JAWANNDENN, UN GIT OPENSOURCE PER DOODLE
Git
https://github.com/hartwork/jawanndenn
Si installa
pip3 install jawanndenn --user
o con git clone
git clone https://github.com/hartwork/jawanndenn
./setup.py install --user
si lancia
jawanndenn
La tua macchina quindi hosta il doodle all indirizzo 127.0.0.1:8080 e si avvia una copia di questa demo qui https://jawanndenn.de/
jawanndenn --help:
--debug Enable debug mode (default: disabled)
--host HOST Hostname or IP address to listen at (dfault 127.0.0.1)
--port PORT Port to listen at (default: 8080)
--url-prefix PATH Path to prepend to URLs (default: "")
--database-sqlite3 FILE File to write the database to (default: ~/jawanndenn.sqlite3)
--django-secret-key-file FILE File to use for Django secret key data (default: ~/jawanndenn.secret_key)
data import/export arguments:
--dumpdata Dump a JSON export of the database to standard output, then quit.
--loaddata FILE.json Load a JSON export of the database from FILE.json, then quit.
-----------------------------------------
# DA FARE PER IMPLEMENTARE CENANDOODLE:
# [AVVIARE JAWANNDENN CON jwndn.json PRECARICATO]
"jawandenn --loaddata file.json" promette di caricare un json precaricato nel doodle ma invece da warnings e errori simili a questi:
WARNINGS:
jawanndenn.Ballot: (models.W042) Auto-created primary key used when not defining a primary key type, by default 'django.db.models.AutoField'.
HINT: Configure the DEFAULT_AUTO_FIELD setting or the AppConfig.default_auto_field attribute to point to a subclass of AutoField, e.g. 'django.db.models.BigAutoField'.
Operations to perform:
Apply all migrations: admin, auth, contenttypes, jawanndenn, sessions
Running migrations:
No migrations to apply.
Importing JSON dump -- this may take a few seconds...
System check identified some issues:
WARNINGS:
jawanndenn.Ballot: (models.W042) Auto-created primary key used when not defining a primary key type, by default 'django.db.models.AutoField'.
HINT: Configure the DEFAULT_AUTO_FIELD setting or the AppConfig.default_auto_field attribute to point to a subclass of AutoField, e.g. 'django.db.models.BigAutoField'.
File "/home/$USER/.local/lib/python3.9/site-packages/django/core/serializers/json.py", line 70, in Deserializer
yield from PythonDeserializer(objects, **options)
File "/home/$USER/.local/lib/python3.9/site-packages/django/core/serializers/python.py", line 103, in Deserializer
Model = _get_model(d["model"])
TypeError: string indices must be integers
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
"/home/$USER/.local/lib/python3.9/site-packages/django/core/serializers/json.py", line 74, in Deserializer
raise DeserializationError() from exc
django.core.serializers.base.DeserializationError: Problem installing fixture '/home/sco/Cenandoodle/jwndn.json':
"Fatayer con Spinaci"
]
}
# [AGGIUNGERE PIU PEZZI DELLO STESSO PRODOTTO PER SINGOLO UTENTE]
scritto dentro a /home/$USER/jawanndenn/jawanndenn/static/js/pool.js c'è:
var VOTED_YES_CLASS = 'votedYes';
var VOTED_NO_CLASS = 'votedNo';
var YET_TO_VOTE_CLASS = 'yetToVote';
stavo cercando di capire come aggiungere un doppio, triplo, quadruplo... voto. In modo da "votare" ovver acquistare/aggiungere ad esempio DUE fatayer al formaggio per singolo user
# [AGGIUNGERE PREZZI DEL PRODOTTO ]
Credo si faccia sempre con /home/$USER/jawanndenn/jawanndenn/static/js/pool.js.
Una possibilità potrebbe essere quella di implementare aggiungendo le liste(prezz o, desc, npezzi) nel javascript facendole comparire tramite un mouseHover. Oppure il prezzo lo si potrebbe aggiungere accanto al nome (e quindi in jwndn.json)
# [GESTIRE LA QUESTIONE DEI PRODOTTI NON DISPONIBILI]
Trovare un modo per determinare quando i prodotti non sono diponibili, eliminandoli dall inclusione del json oppure specificando il "non disponibile"
# [PARSARE IL NUMERO DI TELEFONO]
Per ora so soltanto che alla riga 870 dell html parsato, all interno di uno "< script >" C'è il numero di telefono in forma "allergenPhoneNumber":"3389529446" (o per lo meno così è per Aleppo). Trovare poi un moodo di visualizzarlo, quasi sicuramente nel "title" del json così da visualizzarlo acconto del nome del ristorante.
# [CALCOLARE E VISUALIZZARE IL PREZZO SINGOLO E TOTALE]
Trovare un modo per calcolare il prezzo del singolo user e il prezzo totale da dare al rider
Installa requirement
```bash
#Concedi i permessi di esecuzione al setup
chmod +x ./setup.sh
#Esegui il setup
./setup.sh
```
## UTILIZZO
lancia ScrapeJE
```bash
python3 scrapeje.py
```
# TODO:
||| Ordinare cibo in rete locale o su servizio hostato. A favore del cliente e del ristoratore in termini economici, evitanto commissioni intermediare, ma senza rinunciare alla comodità dei clic <br>
||| Aggiungere più pezzi dello stesso prodotto per singolo utente, <br>
||| calcolare e visualizzare il prezzo del singolo utente e il totale da dare al rider. <br>

115
ScrapeJE.py Normal file
View File

@@ -0,0 +1,115 @@
import requests
from bs4 import BeautifulSoup
import cloudscraper
import json
nome=[]
desc=[]
npezzi=[]
prezzo=[]
#prende l url della pagina justeat del ristorante in input
#linkJE = input('link della pagina justeat del ristorante: ') #decommenta per input manuale
#scrape html
scraper = cloudscraper.create_scraper(browser={'browser': 'firefox','platform': 'windows','mobile': False})
#page = scraper.get(linkJE).content #usa input manuale
page = scraper.get("https://www.justeat.it/restaurants-saporedialeppo/menu").content #usa input automatico
#crea il file html
with open('JEmenu.html', 'wb') as f:
f.write(page)
#apre e legge il file
with open('JEmenu.html', 'rb') as f:
page = f.read()
#parser
soup = BeautifulSoup(page, "html.parser")
menu = soup.find(attrs={"data-test-id": "menu-item"})
#Stora nome ristorante
nrist=soup.title.text[8:-32]
menu.find(attrs={"allergenPhoneNumber": "menu-item-name"})
##
#Stora il numero di telfono del ristorante
#info-> alla riga 870 dell html, all interno di uno <script> c'è il numero in forma-> "allergenPhoneNumber":"3389529446" (es riferito a quando si scrapa aleppo)
#tel=
##
#cicla le schede prodotto
for menu in soup.find_all(attrs={"data-test-id": "menu-item"}):
att=menu
#riempie la lista "nome"
for att in menu.find(attrs={"data-test-id": "menu-item-name"}):
if att != " ":
nome.append(att.lstrip().splitlines()[0])
#riempie la lista "desc"
att=menu.find("p", class_="c-menuItems-description")
if att != None:
for att in menu.find("p", class_="c-menuItems-description"):
desc.append(att.lstrip().splitlines()[0])
else:
desc.append(None)
#riempie la lista "prezzo"
for att in menu.find("p", class_="c-menuItems-price notranslate"):
prezzo.append(att.lstrip().splitlines()[0])
#riempie la lista "npezzi"
att=menu.find_all(attrs={"data-test-id": "menu-item-description"})
if att != None:
if menu.text.find("pezzo") > 0 or menu.text.find("pezzi") > 0:
npezzi.append(menu.text.splitlines()[7].lstrip())
else:
npezzi.append(None)
continue
#stampa liste
for x in range(len(nome)):
print("\n")
print(nome[x])
print(desc[x])
print(npezzi[x])
print(prezzo[x])
#stampa lunghezza liste e nome del risrorante # e numero di telefono
print("\n")
print(nrist)
#print(tel)
print("lista nome",len(nome))
print("lista desc:",len(desc))
print("lista npezzi:",len(npezzi))
print("lista prezzi:",len(prezzo)) #sono stringhe ovvero ci sono anche prezzi come "da 1,00 €" (servirà formattarla in double per poter fare i conti a fine doodle)
#Crea file json formattato per jawanndenn con la lista dei nomi dei prodotti
data = {"lifetime": "month", "equal_width": "true", "title": nrist, "options": nome}
print(json.dumps(data))
def writeListJSONFile(filepathname):
with open('jwndn.json', 'w') as f:
f.write(json.dumps(data))
writeListJSONFile('./jwndn.json')
#
#storare in "tel" il numero di telefono dle ristorante
#automatizzare l inserimento in jawandenn
#PS jawanndenn include la funzione per argomento
#"jawanndenn --loaddata FILE.json" --> Load a JSON export of the database from FILE.json, then quit.
#aggiungere la possibilità di mettere piu di un voto al doodle (ovvero prendere piu prodotti come es: 2 fatayer al formaggio)
#fare in modo che quando si passa il mouse sul nome del prodotto (nel doodle) compaiano descrizione, npezzi e prezzo
#forse per il prezzo trattamento diverso
#

View File

@@ -1,383 +0,0 @@
#IMPORTO MODULI
#selenium: scraper | bs4: parser | re: regex | os: interazione con os | shutil: interazione con la shell
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from bs4 import BeautifulSoup
import re
import os
import shutil
from jinja2 import Template
import time
restaurant_url=''
driver=''
page = ''
nrist=''
restaurant_address=''
tel=''
result=''
soup = ''
nristmax = '0'
nome=[]
desc=[]
npezzi=[]
prezzo=[]
prezzoN=[]
def inputurl():
global restaurant_url
global nristmax
#INPUT
#prende l url della pagina justeat del ristorante in input
print ("\nesempio: https://www.justeat.it/restaurants-pizzeria-la-garganica-bologna/menu")
restaurant_url = input('INSERISCI IL LINK DELLA PAGINA DEL RISTORANTE: ')
# PER DEBUG
#restaurant_url = 'https://www.justeat.it/restaurants-pizzeriadelrondone-bologna/menu'
def animazione():
def typewriter(text, delay=0.1):
for letter in text:
print(letter, end='', flush=True)
time.sleep(delay)
print()
typewriter("▁ ▂ ▃ ▄ ▅ ▆ ▇ █ ▇ ▆ ▅ ▄ ▃ ▁", 0.09)
def scraper():
global driver
global page
global restaurant_url
#FIREFOX
opts = webdriver.FirefoxOptions()
opts.headless = True
driver = webdriver.Firefox(options=opts)
driver.get(restaurant_url)
#CHROMIUM/CHROME
# driver = webdriver.Chrome()
# driver.get(restaurant_url)
animazione()
wait = WebDriverWait(driver, 16)
wait.until(EC.presence_of_element_located((By.CLASS_NAME, "c-menuItems-price")))
page = driver.page_source
with open('JEmenu.html', 'w') as f:
f.write(page)
def parser():
global soup
with open('JEmenu.html', 'r') as f:
page = f.read()
soup = BeautifulSoup(page, "html.parser")
def stora_tutto():
global nome
global desc
global npezzi
global prezzo
global prezzoN
global soup
global nrist
global restaurant_address
global tel
global result
#Stora nome ristorante
nrist = soup.title.text[8:-32]
#Stora telefono del ristorante
pattern = re.compile(r'allergenPhoneNumber')
script_tags = soup.find_all('script', string=pattern)
pattern = re.compile(r'"allergenPhoneNumber":"(\d+)"')
tel = re.search(pattern, script_tags[0].next)
if tel:
tel = tel.group(1)
#Stato ristorante
restaurant_is_open = menu = soup.find(attrs={"data-js-test":"order-status-wrapper"}).text
restaurant_is_open = restaurant_is_open.replace('\n', ' ')
regex = r" {4,}"
result = re.split(regex, restaurant_is_open)
#indirizzo ristorante
restaurant_address = soup.find(attrs={"data-js-test":"header-restaurantAddress"}).text
#cicla le schede prodotto
menu = soup.find(attrs={"data-test-id": "menu-item"})
for menu in soup.find_all(attrs={"data-test-id": "menu-item"}):
att=menu
#riempie la lista "nome"
for att in menu.find(attrs={"data-test-id": "menu-item-name"}):
if att != type(None):
if att != " ":
nome.append(att.lstrip().splitlines()[0])
break
else:
continue
#riempie la lista "desc"
att=menu.find("p", class_="c-menuItems-description")
if att != None:
for att in menu.find("p", class_="c-menuItems-description"):
desc.append(att.lstrip().splitlines()[0])
else:
desc.append(None)
#riempie la lista "prezzo"
for att in menu.find(attrs={"data-js-test": "menu-item-price"}):
#prezzo.append(att.lstrip().splitlines()[0])
counter=0
if att != " " and counter % 2 == 0:
prezzo.append(att.lstrip())
counter+=1
else:
counter+=1
continue
continue
#riempie la lista "npezzi"
att=menu.find_all(attrs={"data-test-id": "menu-item-description"})
if att != None:
if menu.text.find("pezzo") > 0 or menu.text.find("pezzi") > 0:
npezzi.append(menu.text.splitlines()[7].lstrip())
else:
npezzi.append(None)
continue
def parserdarubrica():
global parser
global stora_tutto
folder_path = ('./DATI_RUBRICA/')
for filename in os.listdir(folder_path):
if filename.startswith(scelta):
print(filename)
filename = filename.replace(' ', ' ')
print(filename)
shutil.copy (folder_path + filename, f'./JEmenu.html')
parser()
stora_tutto()
else:
print ("numero inesistente")
continue
def stampa_liste(): #PER DEBUG
print("\n")
for x in range(len(nome)):
# print("\n")
print(nome[x])
print(desc[x])
print(npezzi[x])
print(prezzo[x])
def stampa_info():
print("-" * (len(desc)) + "\n")
print(nrist)
print(restaurant_address.strip())
print("Telefono:",tel,"\n")
doppione = ""
for i in range(len(result)):
if re.search(r"[a-zA-Z]", result[i]):
if (result[i]) == doppione:
continue
else:
print(result[i])
elif re.search(r"\d", result[i]):
print(result[i], result[i+1])
doppione = (result[i+1])
print("\n" + "-" * (len(desc))+ "\n")
def genera_prezzoN():
#Genera la lista prezzoN[] che è un clone di "prezzo[] ma con i valori float anzichè string"
global prezzoN
prezzoN = prezzo.copy()
for i in range(len(prezzo)):
if "" in prezzo[i]:
prezzoN[i] = float(prezzo[i].replace("", "").replace(",", ".").replace("da ", ""))
elif "Non" in prezzo[i]:
prezzoN[i] = 0
prezzoN[i] = float(prezzoN[i])
else:
prezzoN[i] = 99999
# for x in range(len(nome)): #PER DEBUG
# print(prezzoN[x])
html=''
def genera_frontend():
# IMPOSTA E GENERA pagina2.html CON IL FILE htmlpage.html
global nome
global desc
global npezzi
global prezzo
global prezzoN
global html
with open("template.html", "r") as file:
template_content = file.read()
template = Template(template_content)
html = template.render(
nrist=nrist,
nome=nome,
desc=desc,
npezzi=npezzi,
prezzo=prezzo,
prezzoN=prezzoN
)
with open("pagina2.html", "w") as file:
file.write(html)
def salvainrubrica():
global nristmax
maxn=0
def trova_nuovo_numero():
global maxn
file_list = os.listdir('./DATI_RUBRICA')
number_list = []
# Estare il numero
for file_name in file_list:
if file_name[0].isdigit():
number_list.append(int(file_name.split('-')[0]))
# trova il massimo
if number_list:
max_number = max(number_list)
maxn=(max_number + 1)
if os.path.exists('rubrica.txt'):
#SE LA RUBRICA ESISTE
with open('rubrica.txt', 'a+') as rubrica:
rubrica.seek(0)
data = rubrica.read()
if restaurant_url not in data:
#QUANDO IL RISTORATE NON E' PRESENTE IN RUBRICA
saveit = input('Vuoi salvare il ristorante in rubrica? [Y|N] ')
#PER DEBUG
#saveit = "y"
if saveit.upper() in ['YES', 'Y', 'SI', 'S']:
os.makedirs("DATI_RUBRICA", exist_ok=True)
trova_nuovo_numero()
nristmax=(str(maxn) + "-" + nrist + '.html')
shutil.move ('JEmenu.html', f'./DATI_RUBRICA/{nristmax}')
if data:
rubrica.write('\n')
rubrica.write(nristmax + '\n')
rubrica.write(nrist + '\n')
rubrica.write(restaurant_url + '\n')
print ('\nIl ristorante"',nrist + '" è stato salvato in rubrica\n')
else:
#QUANDO IL RISTORATE E' GIA' PRESENTE IN RUBRICA
os.remove("JEmenu.html")
else:
#QUANDO IL RISTORATE E' GIA' PRESENTE IN RUBRICA
os.remove("JEmenu.html")
else:
#SE LA RUBRICA NON ESISTE
with open('rubrica.txt', 'a+') as rubrica:
rubrica.seek(0)
data = rubrica.read()
#CHIEDE SE SI VUOLE SALVARE ALTRIMENTI PULISCE
saveit = input('Vuoi salvare il ristorante in rubrica? [Y|N] ')
#PER DEBUG
#saveit = "y"
if saveit.upper() in ['YES', 'Y', 'SI', 'S']:
os.makedirs("DATI_RUBRICA", exist_ok=True)
nristmax=("1" + "-" + nrist + '.html')
shutil.move ('JEmenu.html', f'./DATI_RUBRICA/{nristmax}')
if data:
rubrica.write('\n')
rubrica.write(nristmax + '\n')
rubrica.write(nrist + '\n')
rubrica.write(restaurant_url + '\n')
print ('\nIl ristorante "' + nrist + '" è stato salvato in rubrica')
print ('(Riavvia lo script per ordinare da rubrica)\n')
else:
#PULISCE
os.remove("JEmenu.html")
os.remove("rubrica.txt")
#############################################################################################
#############################################################################################
#############################################################################################
if os.path.exists('rubrica.txt') and os.path.exists('./DATI_RUBRICA'):
#wr = input('\nVuoi vedere la rubrica? [Y|N] ')
wr = 's'
if wr.upper() in ['YES', 'Y', 'SI', 'S']:
print( '\n', os.listdir('./DATI_RUBRICA'), '\n')
#scelta = input("Scegli un numero esistente o premi Enter per metterre un link: ")
scelta = '1'
parserdarubrica()
else:
inputurl()
scraper()
parser()
stora_tutto()
driver.quit()
else:
inputurl()
scraper()
parser()
stora_tutto()
driver.quit()
stampa_liste()
stampa_info()
genera_prezzoN()
salvainrubrica()
genera_frontend()
driver = webdriver.Firefox()
animazione()
driver.get("file://" + os.path.abspath("pagina2.html"))
# #PER DEBUG
# for x in range(len(prezzoN)):
# print(prezzoN[x])
# print("\n" + "-" * 25 + "\n")
# print ("lista prezzo: ",len(prezzo))
# print ("lista prezzoN: ",len(prezzoN))
# print ("lista nome: ",len(nome))
# print("\n" + "-" * 25 + "\n")
# #PER DEBUG
#stampa lunghezza liste
# print("lista nome: ",len(nome))
# print("lista desc: ",len(desc))
# print("lista npezzi: ",len(npezzi))
# print("lista prezzi: ",len(prezzo)) #sono stringhe
# print("lista prezziN: ",len(prezzoN)) #sono numeri
# print("\n" + "-" * 25 + "\n")
#FA SCHIFO
# html += ' var popup = window.open("", "Popup", "width=200,height=100,top=" + ((window.innerHeight - 100) / 2) + ",left=" + ((window.innerWidth - 200) / 2));'
# html += ' popup.document.write("<p>Prodotto aggiunto</p>");'
# html += ' setTimeout(function(){ popup.close(); }, 1000);'

33
setup.sh Executable file → Normal file
View File

@@ -1,32 +1,5 @@
#!/bin/bash
echo "Installo i moduli python necessari nella cartella .venv"
python -m venv .venv
source .venv/bin/activate
echo
#!/bin/sh
pip3 install jawanndenn
pip3 install requests
pip3 install BeautifulSoup4
pip3 install selenium
#SCRAPEJE UTILIZZA I MODULI PREINSTALLATI:
# import re
# import os
# import shutil
#NON PIU UTILIZZATI:
# pip3 install colorama
# pip3 install cloudscraper
# pip3 install json
echo "Installo chromium (se non già installato) necessario per lo scrape"
echo
sudo apt update
if [ -f /etc/os-release ] && grep -q "NAME=\"Ubuntu\"" /etc/os-release; then
sudo apt install chromium-browser -y
else
sudo apt install chromium -y
fi
echo
echo "Attiva il virtualenv: source .venv/bin/activate"
echo "Poi lancia lo script: python3 scrapeje.py"
echo
pip3 install cloudscraper

4
start.sh Normal file
View File

@@ -0,0 +1,4 @@
#!/bin/sh
python3 ScrapeJE.py
wait 1
jawanndenn --loaddata jwndn.json

View File

@@ -1,76 +0,0 @@
<html>
<head>
<!-- <link rel="stylesheet" type="text/css" href="main.css" /> -->
<style>
.container {
display: grid;
grid-template-columns: auto auto auto;
padding: 10px;
}
.grid-item {
/* background-color: rgba(255, 255, 255, 0.8); */
border: 1px solid #ff8d1a;
padding: 20px;
/* font-size: 30px; */
text-align: center;
/* grid-column-start: 1;
grid-column-end: 3; */
}
</style>
<body style="background-color: black; color: white">
<h1 style='text-align: center; color: #ff8d1a'>{{ nrist }} </h1>
<!-- <form id="usernameForm">
<input type="text" id="prodottiAggiunti" placeholder="Enter your username" />
<button type="button" onclick="addUser()">Add User</button>
</form> -->
</head>
<br><br>
<div class="container">
{% for index in range(nome|length) %}
<div class="grid-item">
<h2 style='text-align: center;'>{{ nome[index] }}</h2>
<div class="spazio">
<p style='text-align: center;'>{{ desc[index] }}</p>
</div>
<p style='text-align: center;'>Npezzi: {{ npezzi[index] }}</p>
<p style='text-align: center;'>{{ prezzoN[index] }}€</p>
<div style='text-align: center;'><button style='font-size: 1.2em;' onclick="aggiungiProdotto('{{ nome[index] }}', '{{ prezzoN[index] }}')">+1</button></div>
</div>
{% endfor %}
</div>
<br><hr><h2>Prodotti aggiunti</h2>
<div id="prodottiAggiunti"></div>
<div id="total">Total: €<span id="totalValue">0.00</span></div>
<script>
var totalValue = 0;
function aggiungiProdotto(nome, prezzoN) {
var prodotto = nome + ' (' + Number(prezzoN).toFixed(2) + '€)';
var box = document.getElementById('prodottiAggiunti');
box.innerHTML += '<p>' + prodotto + ' <button onclick="rimuoviProdotto(this, ' + prezzoN + ')">-1</button></p>';
totalValue += parseFloat(prezzoN);
updateTotal();
}
function updateTotal() {
document.getElementById('totalValue').innerText = totalValue.toFixed(2);
}
function rimuoviProdotto(element, prezzoN) {
totalValue -= parseFloat(prezzoN);
element.parentNode.remove();
updateTotal();
}
</script>
</body>
</html>