from flask import Flask, request, jsonify from database import * from werkzeug.utils import secure_filename app = Flask(__name__) app.config['UPLOAD_FOLDER'] = os.path.join(app.root_path, 'photos') app.config['URL_PREFIX'] = '/uploads' # public URL prefix # make sure the folder exists os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True) # helper to build a public URL def public_url(filename: str) -> str: return f"{app.config['URL_PREFIX']}/{filename}" # Initialise database on startup initialize_db() # ----------------------------- Users ----------------------------- @app.route("/users", methods=["GET", "POST"]) def users(): if request.method == "GET": # Optional query parameters name = request.args.get("name") id = request.args.get("id", type=int) username = request.args.get("username") fields = request.args.get("fields") fields = fields.split(",") if fields else None users = get_user(name=name, id=id, username=username, fields=fields) return jsonify(users) if request.method == "POST": data = request.get_json() if not data: return jsonify({"error": "Missing JSON body"}), 400 name = data.get("name") age = data.get("age") photo = data.get("photo") username = data.get("username") if not all([name, age, username]): return jsonify({"error": "name, age and username required"}), 400 result = add_user(name, age, photo, username) return jsonify(result), 201 @app.route("/users/", methods=["PUT"]) def update_user_route(user_id: int): data = request.get_json() if not data: return jsonify({"error": "Missing JSON body"}), 400 name = data.get("name") photo = data.get("photo") settings = data.get("settings") result = update_user(user_id, name=name, photo=photo, settings=settings) return jsonify(result) # ----------------------------- Providers ----------------------------- @app.route("/providers", methods=["GET", "POST"]) def providers(): if request.method == "GET": name = request.args.get("name") id = request.args.get("id", type=int) phone = request.args.get("phone") fields = request.args.get("fields") fields = fields.split(",") if fields else None provs = get_provider(name=name, id=id, phone=phone, fields=fields) return jsonify(provs) if request.method == "POST": data = request.get_json() if not data: return jsonify({"error": "Missing JSON body"}), 400 name = data.get("name") age = data.get("age") photo = data.get("photo") phone = data.get("phone") rates = data.get("rates", {}) private = data.get("private", False) if not all([name, age, phone]): return jsonify({"error": "name, age and phone required"}), 400 result = add_provider(name, age, photo, phone, rates, private) return jsonify(result), 201 @app.route("/providers/", methods=["PUT"]) def update_provider_route(prov_id: int): data = request.get_json() if not data: return jsonify({"error": "Missing JSON body"}), 400 name = data.get("name") phone = data.get("phone") rates = data.get("rates") private = data.get("private") photo = data.get("photo") result = update_provider(prov_id, name=name, phone=phone, rates=rates, private=private, photo=photo) return jsonify(result) # ----------------------------- Visits ----------------------------- @app.route("/visits", methods=["GET", "POST"]) def visits(): if request.method == "GET": provider = request.args.get("provider", type=int) user = request.args.get("user", type=int) start = request.args.get("start") end = request.args.get("end") date_range = [start, end] if start and end else None visits_list = get_visits(provider=provider, user=user, date_range=date_range) return jsonify(visits_list) if request.method == "POST": data = request.get_json() if not data: return jsonify({"error": "Missing JSON body"}), 400 user_ids = data.get("user_ids", []) provider_ids = data.get("provider_ids", []) cost = data.get("cost") location = data.get("location") time = data.get("time") if not (user_ids and provider_ids and time): return jsonify({"error": "user_ids, provider_ids and time required"}), 400 result = add_visit(user_ids, provider_ids, cost, location, time) return jsonify(result), 201 @app.route("/visits/", methods=["PUT"]) def update_visit_route(visit_id: int): data = request.get_json() if not data: return jsonify({"error": "Missing JSON body"}), 400 user_ids = data.get("user_ids") provider_ids = data.get("provider_ids") cost = data.get("cost") location = data.get("location") time = data.get("time") result = update_visit(visit_id, user_ids=user_ids, provider_ids=provider_ids, cost=cost, location=location, time=time) return jsonify(result) # ----------------------------- Settings ----------------------------- @app.route("/settings", methods=["GET", "POST"]) def settings_collection(): """Handle collection of settings. * GET: Return all settings. * POST: Add or replace a setting. Expects JSON with ``name`` and ``value``. """ if request.method == "GET": # Return all settings print(view_settings()) return jsonify(view_settings()) if request.method == "POST": data = request.get_json() if not data: return jsonify({"error": "Missing JSON body"}), 400 name = data.get("name") value = data.get("value") if not name or value is None: return jsonify({"error": "name and value required"}), 400 result = add_setting(name, value) print(result) return jsonify(result), 201 @app.route("/settings/", methods=["GET", "PUT"]) def setting_detail(name: str): """Retrieve or update a single setting. * GET: Return the setting with the given name. * PUT: Update the setting value. Expects JSON with ``value``. """ if request.method == "GET": rows = view_settings([name]) if not rows: return jsonify({"error": "Setting not found"}), 404 print(rows[0]) return jsonify(rows[0]) if request.method == "PUT": data = request.get_json() if not data: return jsonify({"error": "Missing JSON body"}), 400 value = data.get("value") if value is None: return jsonify({"error": "value required"}), 400 result = change_setting(name, value) print(result) return jsonify(result) # ----------------------------- Photos ----------------------------- # photo upload endpoint @app.route('/api/providers//photos', methods=['POST']) def upload_photos(provider_id): if 'photos' not in request.files: return jsonify({'error': 'No files uploaded'}), 400 files = request.files.getlist('photos') if not files: return jsonify({'error': 'No files in list'}), 400 allowed_ext = {'.jpg', '.jpeg', '.png', '.gif'} saved_filenames = [] for f in files: if f.filename == '': continue filename = secure_filename(f.filename) ext = os.path.splitext(filename)[1].lower() if ext not in allowed_ext: return jsonify({'error': f'Unsupported file type: {ext}'}), 400 # rename to avoid collisions new_name = f"{uuid.uuid4().hex}{ext}" f.save(os.path.join(app.config['UPLOAD_FOLDER'], new_name)) saved_filenames.append(public_url(new_name)) # Merge with any pre‑existing photos existing = db.fetch(f"SELECT photos FROM providers WHERE id=?", (provider_id,))[0][0] try: photos = json.loads(existing) except Exception: photos = [] photos.extend(saved_filenames) db.execute("UPDATE providers SET photos = %s WHERE id = %s", (json.dumps(photos), provider_id)) return jsonify({'success': True, 'photos': photos}), 200 # Endpoint to change the main photo @app.route('/api/providers//main_photo', methods=['PUT']) def set_main_photo(provider_id): data = request.get_json() url = data.get('url') if not url: return jsonify({'error': 'Missing url'}), 400 # Validate that the URL belongs to this provider photos = db.fetch(f"SELECT photos FROM providers WHERE id=?", (provider_id,))[0][0] if json.loads(photos).count(url) == 0: return jsonify({'error': 'URL not part of this provider'}), 400 db.execute("UPDATE providers SET main_photo = %s WHERE id = %s", (url, provider_id)) return jsonify({'success': True, 'main_photo': url}) # Run the app if this file is executed directly if __name__ == "__main__": app.run(host="0.0.0.0", port=5000, debug=False)