add initial template
This commit is contained in:
parent
4ed1e88dc2
commit
45a93e5a23
13 changed files with 457 additions and 13 deletions
58
.gitignore
vendored
58
.gitignore
vendored
|
@ -1,2 +1,56 @@
|
|||
.idea
|
||||
backend/.env
|
||||
# Virtual environment
|
||||
venv/
|
||||
env/
|
||||
.venv/
|
||||
|
||||
# Python
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
*.so
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
|
||||
# IDE
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
.DS_Store?
|
||||
._*
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
ehthumbs.db
|
||||
Thumbs.db
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
|
||||
# Environment variables
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# Node modules (se installi http-server globalmente)
|
||||
node_modules/
|
||||
|
||||
# Docker
|
||||
.dockerignore
|
18
README.md
18
README.md
|
@ -1,2 +1,18 @@
|
|||
# Team NPT
|
||||
# Template per Hackathon
|
||||
|
||||
## 🚀 Avvio Rapido
|
||||
|
||||
```bash
|
||||
# Avvia tutto con un comando
|
||||
./start.sh
|
||||
|
||||
#Comandi utili per vedere dati db su mongosh
|
||||
mongosh
|
||||
show dbs
|
||||
use simple_db
|
||||
show collections
|
||||
db.items.find()
|
||||
```
|
||||
|
||||
Il frontend sarà disponibile su http://localhost:3000
|
||||
Il backend sarà hostato localmente su http://localhost:8000
|
97
app/index.html
Normal file
97
app/index.html
Normal file
|
@ -0,0 +1,97 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="it">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Template APP</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
max-width: 800px;
|
||||
margin: 50px auto;
|
||||
padding: 20px;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.container {
|
||||
background: white;
|
||||
padding: 30px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||
}
|
||||
h1 {
|
||||
color: #333;
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
.button-group {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
justify-content: center;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
button {
|
||||
padding: 15px 30px;
|
||||
font-size: 16px;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
.btn-get {
|
||||
background-color: #4CAF50;
|
||||
color: white;
|
||||
}
|
||||
.btn-get:hover {
|
||||
background-color: #45a049;
|
||||
}
|
||||
.btn-post {
|
||||
background-color: #2196F3;
|
||||
color: white;
|
||||
}
|
||||
.btn-post:hover {
|
||||
background-color: #1976D2;
|
||||
}
|
||||
.result {
|
||||
background-color: #f9f9f9;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 5px;
|
||||
padding: 20px;
|
||||
margin-top: 20px;
|
||||
white-space: pre-wrap;
|
||||
font-family: monospace;
|
||||
max-height: 400px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.status {
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.success {
|
||||
background-color: #d4edda;
|
||||
color: #155724;
|
||||
border: 1px solid #c3e6cb;
|
||||
}
|
||||
.error {
|
||||
background-color: #f8d7da;
|
||||
color: #721c24;
|
||||
border: 1px solid #f5c6cb;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>🚀 Simple Fullstack App</h1>
|
||||
|
||||
<div class="button-group">
|
||||
<button class="btn-get" onclick="getData()">📥 GET Data</button>
|
||||
<button class="btn-post" onclick="createData()">📤 POST Data</button>
|
||||
</div>
|
||||
|
||||
<div id="status"></div>
|
||||
<div id="result" class="result" style="display: none;"></div>
|
||||
</div>
|
||||
|
||||
<script src="script.js"></script>
|
||||
</body>
|
||||
</html>
|
76
app/script.js
Normal file
76
app/script.js
Normal file
|
@ -0,0 +1,76 @@
|
|||
const API_BASE_URL = 'http://localhost:8000';
|
||||
|
||||
// Funzione per mostrare messaggi di status
|
||||
function showStatus(message, isSuccess = true) {
|
||||
const statusDiv = document.getElementById('status');
|
||||
statusDiv.innerHTML = `<div class="status ${isSuccess ? 'success' : 'error'}">${message}</div>`;
|
||||
}
|
||||
|
||||
// Funzione per mostrare i risultati
|
||||
function showResult(data) {
|
||||
const resultDiv = document.getElementById('result');
|
||||
resultDiv.style.display = 'block';
|
||||
resultDiv.textContent = JSON.stringify(data, null, 2);
|
||||
}
|
||||
|
||||
// GET: Ottiene dati dal database
|
||||
async function getData() {
|
||||
try {
|
||||
console.log('📥 Richiesta GET in corso...');
|
||||
showStatus('📥 Richiesta GET in corso...', true);
|
||||
|
||||
const response = await fetch(`${API_BASE_URL}/api/data`);
|
||||
const data = await response.json();
|
||||
|
||||
if (response.ok) {
|
||||
showStatus('✅ Dati ottenuti con successo!', true);
|
||||
showResult(data);
|
||||
} else {
|
||||
showStatus(`❌ Errore: ${data.detail || 'Errore sconosciuto'}`, false);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Errore GET:', error);
|
||||
showStatus(`❌ Errore di connessione: ${error.message}`, false);
|
||||
}
|
||||
}
|
||||
|
||||
// POST: Inserisce dati nel database
|
||||
async function createData() {
|
||||
try {
|
||||
console.log('📤 Richiesta POST in corso...');
|
||||
showStatus('📤 Richiesta POST in corso...', true);
|
||||
|
||||
const response = await fetch(`${API_BASE_URL}/api/data`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (response.ok) {
|
||||
showStatus('✅ Dato inserito con successo!', true);
|
||||
showResult(data);
|
||||
} else {
|
||||
showStatus(`❌ Errore: ${data.detail || 'Errore sconosciuto'}`, false);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Errore POST:', error);
|
||||
showStatus(`❌ Errore di connessione: ${error.message}`, false);
|
||||
}
|
||||
}
|
||||
|
||||
// Test di connessione all'avvio
|
||||
window.addEventListener('load', async () => {
|
||||
try {
|
||||
const response = await fetch(`${API_BASE_URL}/`);
|
||||
if (response.ok) {
|
||||
console.log('✅ Backend connesso!');
|
||||
} else {
|
||||
console.log('❌ Backend non raggiungibile');
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('❌ Backend non raggiungibile:', error.message);
|
||||
}
|
||||
});
|
|
@ -1,3 +0,0 @@
|
|||
# ENV
|
||||
- MONGO_INITDB_ROOT_USERNAME=
|
||||
- MONGO_INITDB_ROOT_PASSWORD=
|
|
@ -1,15 +1,30 @@
|
|||
version: '3.8'
|
||||
|
||||
services:
|
||||
mongodb:
|
||||
image: mongo:8.0.0
|
||||
container_name: mongodb
|
||||
restart: unless-stopped
|
||||
image: mongo:7.0
|
||||
container_name: simple_mongodb
|
||||
ports:
|
||||
- "27017:27017"
|
||||
environment:
|
||||
- MONGO_INITDB_ROOT_USERNAME=${MONGO_INITDB_ROOT_USERNAME}
|
||||
- MONGO_INITDB_ROOT_PASSWORD=${MONGO_INITDB_ROOT_PASSWORD}
|
||||
MONGO_INITDB_ROOT_USERNAME: admin
|
||||
MONGO_INITDB_ROOT_PASSWORD: password
|
||||
volumes:
|
||||
- mongo-data:/data/db
|
||||
- mongodb_data:/data/db
|
||||
restart: unless-stopped
|
||||
|
||||
mongo-express:
|
||||
image: mongo-express:latest
|
||||
container_name: mongo_express
|
||||
ports:
|
||||
- "8081:8081"
|
||||
environment:
|
||||
ME_CONFIG_MONGODB_ADMINUSERNAME: admin
|
||||
ME_CONFIG_MONGODB_ADMINPASSWORD: password
|
||||
ME_CONFIG_MONGODB_URL: mongodb://admin:password@mongodb:27017/
|
||||
depends_on:
|
||||
- mongodb
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
mongo-data:
|
||||
mongodb_data:
|
||||
|
|
22
backend/main.py
Normal file
22
backend/main.py
Normal file
|
@ -0,0 +1,22 @@
|
|||
from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from routes import router
|
||||
|
||||
app = FastAPI(title="Simple Fullstack API")
|
||||
|
||||
# CORS per permettere richieste dal frontend
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=["*"],
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
# Includi le route
|
||||
app.include_router(router)
|
||||
|
||||
if __name__ == "__main__":
|
||||
import uvicorn
|
||||
print("🚀 Avvio server FastAPI...")
|
||||
uvicorn.run(app, host="0.0.0.0", port=8000)
|
|
@ -0,0 +1,4 @@
|
|||
fastapi==0.104.1
|
||||
uvicorn[standard]==0.24.0
|
||||
pymongo==4.6.0
|
||||
python-multipart==0.0.6
|
50
backend/routes.py
Normal file
50
backend/routes.py
Normal file
|
@ -0,0 +1,50 @@
|
|||
from fastapi import APIRouter, HTTPException
|
||||
from pymongo import MongoClient
|
||||
from datetime import datetime
|
||||
|
||||
# Router per le API
|
||||
router = APIRouter()
|
||||
|
||||
# Connessione MongoDB
|
||||
client = MongoClient("mongodb://localhost:27017/")
|
||||
db = client["simple_db"]
|
||||
collection = db["items"]
|
||||
|
||||
@router.get("/")
|
||||
def read_root():
|
||||
"""Root endpoint per test connessione"""
|
||||
return {"message": "Simple Fullstack API is running!"}
|
||||
|
||||
@router.get("/api/data")
|
||||
def get_data():
|
||||
"""GET: Ottiene il primo documento dal database"""
|
||||
try:
|
||||
# Trova il primo documento disponibile
|
||||
document = collection.find_one()
|
||||
if document:
|
||||
# Converti ObjectId in stringa per JSON serialization
|
||||
document["_id"] = str(document["_id"])
|
||||
return {"success": True, "data": document}
|
||||
else:
|
||||
return {"success": False, "message": "Nessun dato trovato nel database"}
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Errore database: {str(e)}")
|
||||
|
||||
@router.post("/api/data")
|
||||
def create_data():
|
||||
"""POST: Inserisce un dato hardcoded nel database"""
|
||||
try:
|
||||
# Dato hardcoded da inserire
|
||||
new_item = {
|
||||
"name": "Item di esempio",
|
||||
"description": "Questo è un item creato tramite API",
|
||||
"timestamp": datetime.now().isoformat(),
|
||||
"value": 42
|
||||
}
|
||||
|
||||
result = collection.insert_one(new_item)
|
||||
new_item["_id"] = str(result.inserted_id)
|
||||
|
||||
return {"success": True, "message": "Dato inserito con successo", "data": new_item}
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Errore inserimento: {str(e)}")
|
113
start.sh
Executable file
113
start.sh
Executable file
|
@ -0,0 +1,113 @@
|
|||
#!/bin/bash
|
||||
|
||||
echo "🚀 Avvio Simple Fullstack App..."
|
||||
|
||||
# Colori per output
|
||||
GREEN='\033[0;32m'
|
||||
BLUE='\033[0;34m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Funzione per stampare messaggi colorati
|
||||
print_status() {
|
||||
echo -e "${BLUE}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
print_success() {
|
||||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||||
}
|
||||
|
||||
print_warning() {
|
||||
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||
}
|
||||
|
||||
# Controlla se Python3 è installato
|
||||
if ! command -v python3 &> /dev/null; then
|
||||
echo "❌ Python3 non trovato. Installa Python3 prima di continuare."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Controlla se Docker è installato
|
||||
if ! command -v docker &> /dev/null; then
|
||||
echo "❌ Docker non trovato. Installa Docker prima di continuare."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Controlla se http-server è installato
|
||||
if ! command -v http-server &> /dev/null; then
|
||||
print_warning "http-server non trovato. Installando..."
|
||||
npm install -g http-server
|
||||
fi
|
||||
|
||||
# Crea virtual environment se non esiste
|
||||
if [ ! -d "venv" ]; then
|
||||
print_status "Creazione virtual environment..."
|
||||
python3 -m venv venv
|
||||
print_success "Virtual environment creato!"
|
||||
else
|
||||
print_status "Virtual environment già esistente"
|
||||
fi
|
||||
|
||||
# Attiva virtual environment
|
||||
print_status "Attivazione virtual environment..."
|
||||
source venv/bin/activate
|
||||
|
||||
# Installa dipendenze
|
||||
print_status "Installazione dipendenze Python..."
|
||||
pip install -r backend/requirements.txt
|
||||
print_success "Dipendenze installate!"
|
||||
|
||||
# Avvia MongoDB con Docker
|
||||
print_status "Avvio MongoDB con Docker..."
|
||||
cd backend
|
||||
docker-compose up -d
|
||||
cd ..
|
||||
|
||||
# Aspetta che MongoDB sia pronto
|
||||
print_status "Attesa MongoDB..."
|
||||
sleep 5
|
||||
|
||||
# Avvia backend in background
|
||||
print_status "Avvio backend FastAPI..."
|
||||
cd backend
|
||||
python main.py &
|
||||
BACKEND_PID=$!
|
||||
cd ..
|
||||
|
||||
# Aspetta che il backend sia pronto
|
||||
print_status "Attesa backend..."
|
||||
sleep 3
|
||||
|
||||
# Avvia frontend
|
||||
print_status "Avvio frontend..."
|
||||
cd app
|
||||
http-server -p 3000 -o &
|
||||
FRONTEND_PID=$!
|
||||
cd ..
|
||||
|
||||
print_success "🎉 Tutto avviato!"
|
||||
echo ""
|
||||
echo "📱 Frontend: http://localhost:3000"
|
||||
echo "🔧 Backend API: http://localhost:8000"
|
||||
echo "🗄️ MongoDB: localhost:27017"
|
||||
echo ""
|
||||
echo "💡 Premi Ctrl+C per fermare tutto"
|
||||
|
||||
# Funzione per cleanup
|
||||
cleanup() {
|
||||
echo ""
|
||||
print_status "Fermando servizi..."
|
||||
kill $BACKEND_PID 2>/dev/null
|
||||
kill $FRONTEND_PID 2>/dev/null
|
||||
cd backend
|
||||
docker-compose down
|
||||
cd ..
|
||||
print_success "Servizi fermati!"
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Intercetta Ctrl+C
|
||||
trap cleanup SIGINT
|
||||
|
||||
# Mantieni lo script in esecuzione
|
||||
wait
|
Loading…
Add table
Add a link
Reference in a new issue