138 lines
4.0 KiB
Python
138 lines
4.0 KiB
Python
from flask import Flask, request, jsonify
|
||
from flask_cors import CORS
|
||
import json
|
||
import os
|
||
from datetime import datetime
|
||
|
||
app = Flask(__name__)
|
||
CORS(app) # Enable CORS for all routes
|
||
|
||
# Data directory and file
|
||
DATA_DIR = 'data'
|
||
DATA_FILE = os.path.join(DATA_DIR, 'journeys.json')
|
||
os.makedirs(DATA_DIR, exist_ok=True)
|
||
|
||
# In-memory store (loaded from file on startup)
|
||
journeys = []
|
||
|
||
def load_journeys():
|
||
"""Load journeys from the JSON file."""
|
||
global journeys
|
||
try:
|
||
if os.path.exists(DATA_FILE):
|
||
with open(DATA_FILE, 'r') as f:
|
||
journeys = json.load(f)
|
||
else:
|
||
journeys = []
|
||
except Exception as e:
|
||
print(f"Error loading journeys: {e}")
|
||
journeys = []
|
||
|
||
def save_journeys():
|
||
"""Save journeys to the JSON file."""
|
||
try:
|
||
with open(DATA_FILE, 'w') as f:
|
||
json.dump(journeys, f, indent=2)
|
||
except Exception as e:
|
||
print(f"Error saving journeys: {e}")
|
||
|
||
# Load existing journeys on startup
|
||
load_journeys()
|
||
|
||
def get_next_id():
|
||
"""Return the next available ID (simple integer increment)."""
|
||
if not journeys:
|
||
return 1
|
||
return max(j['id'] for j in journeys) + 1
|
||
|
||
@app.route('/api/journeys', methods=['POST'])
|
||
def create_journey():
|
||
"""Create a new journey."""
|
||
data = request.get_json()
|
||
if not data:
|
||
return jsonify({'error': 'No data provided'}), 400
|
||
|
||
title = data.get('title')
|
||
if not title:
|
||
return jsonify({'error': 'Journey title is required'}), 400
|
||
|
||
new_journey = {
|
||
'id': get_next_id(),
|
||
'title': title,
|
||
'description': data.get('description', ''),
|
||
'markers': data.get('markers', []), # list of marker objects
|
||
'created_at': datetime.now().isoformat()
|
||
}
|
||
|
||
journeys.append(new_journey)
|
||
save_journeys()
|
||
return jsonify(new_journey), 201
|
||
|
||
@app.route('/api/journeys', methods=['GET'])
|
||
def get_journeys():
|
||
"""Return all journeys."""
|
||
return jsonify(journeys)
|
||
|
||
@app.route('/api/journeys/<int:journey_id>', methods=['GET'])
|
||
def get_journey(journey_id):
|
||
"""Return a specific journey by ID."""
|
||
journey = next((j for j in journeys if j['id'] == journey_id), None)
|
||
if journey is None:
|
||
return jsonify({'error': 'Journey not found'}), 404
|
||
return jsonify(journey)
|
||
|
||
@app.route('/api/journeys/<int:journey_id>', methods=['PUT'])
|
||
def update_journey(journey_id):
|
||
"""Update an existing journey."""
|
||
journey = next((j for j in journeys if j['id'] == journey_id), None)
|
||
if journey is None:
|
||
return jsonify({'error': 'Journey not found'}), 404
|
||
|
||
data = request.get_json()
|
||
if not data:
|
||
return jsonify({'error': 'No data provided'}), 400
|
||
|
||
# Update allowed fields
|
||
if 'title' in data:
|
||
journey['title'] = data['title']
|
||
if 'description' in data:
|
||
journey['description'] = data['description']
|
||
if 'markers' in data:
|
||
journey['markers'] = data['markers']
|
||
|
||
save_journeys()
|
||
return jsonify(journey)
|
||
|
||
@app.route('/api/journeys/<int:journey_id>', methods=['DELETE'])
|
||
def delete_journey(journey_id):
|
||
"""Delete a journey."""
|
||
global journeys
|
||
journey = next((j for j in journeys if j['id'] == journey_id), None)
|
||
if journey is None:
|
||
return jsonify({'error': 'Journey not found'}), 404
|
||
|
||
journeys = [j for j in journeys if j['id'] != journey_id]
|
||
save_journeys()
|
||
return jsonify({'message': 'Journey deleted successfully', 'journey': journey})
|
||
|
||
@app.route('/api/journeys/health', methods=['GET'])
|
||
def health_check():
|
||
"""Simple health check endpoint."""
|
||
return jsonify({'status': 'healthy', 'timestamp': datetime.now().isoformat()})
|
||
|
||
@app.route('/')
|
||
def index():
|
||
"""Root endpoint – just a welcome message."""
|
||
return '''
|
||
<!DOCTYPE html>
|
||
<html>
|
||
<head><title>Journey Mapper Backend</title></head>
|
||
<body>
|
||
<h1>Journey Mapper API</h1>
|
||
<p>Backend is running. Use <code>/api/journeys</code> endpoints.</p>
|
||
</body>
|
||
</html>
|
||
'''
|
||
|
||
if __name__ == '__main__':
|
||
app.run(debug=True, port=5000) |