Skip to content

Develop #20

Merged
merged 3 commits into from
Apr 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added backend/images/buddy.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added backend/images/rex.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added backend/images/whiskers.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
342 changes: 342 additions & 0 deletions backend/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,342 @@
from flask import Flask, jsonify, request, send_from_directory
from flask_cors import CORS
from flasgger import Swagger
import os
from pets import add_pet, update_pet, delete_pet, search_pets, reset_pets

app = Flask(__name__)
app.secret_key = "test_secret_key"
CORS(app)

# Set up Swagger documentation
swagger_config = {
"title": "Animal Shelter API",
"version": "1.0.0",
"description": "API for animal adoption management"
}
swagger = Swagger(app, config=swagger_config)

# Mock data for testing
ANIMALS = [
{
"id": 1,
"name": "Luna",
"species": "Dog",
"breed": "Labrador Mix",
"age": 2,
"personality": "Playful and energetic",
"image_path": "/images/luna.jpg",
"adoption_status": "Available"
},
{
"id": 2,
"name": "Oliver",
"species": "Cat",
"breed": "Tabby",
"age": 4,
"personality": "Independent but affectionate",
"image_path": "/images/oliver.jpg",
"adoption_status": "Available"
},
{
"id": 3,
"name": "Max",
"species": "Dog",
"breed": "German Shepherd",
"age": 3,
"personality": "Loyal and intelligent",
"image_path": "/images/max.jpg",
"adoption_status": "Available"
}
]

USERS = [
{
"id": 1,
"username": "admin",
# In a real app, this would be hashed, but for testing it's plain text
"password": "admin123",
"email": "admin@example.com"
}
]

# User registration endpoint
@app.route('/api/register', methods=['POST'])
def register_user():
"""
Register a new adopter
---
parameters:
- in: body
name: user
description: User registration details
schema:
type: object
required:
- username
- password
- email
properties:
username:
type: string
password:
type: string
email:
type: string
responses:
201:
description: User registered successfully
400:
description: Missing required fields
409:
description: Username already exists
"""
data = request.get_json()
username = data.get('username')
password = data.get('password')
email = data.get('email')

if not username or not password or not email:
return jsonify({'error': 'All fields are required'}), 400

# Check if username already exists
if any(user['username'] == username for user in USERS):
return jsonify({'error': 'Username already exists'}), 409

# Check if email already exists
if any(user['email'] == email for user in USERS):
return jsonify({'error': 'Email already registered'}), 409

# Create new user
new_user = {
"id": len(USERS) + 1,
"username": username,
"password": password, # In real app, would be hashed
"email": email
}
USERS.append(new_user)

return jsonify({'message': 'Registration successful!', 'user_id': new_user['id']}), 201

# User login endpoint
@app.route('/api/login', methods=['POST'])
def authenticate_user():
"""
User login
---
parameters:
- in: body
name: credentials
description: Login credentials
schema:
type: object
required:
- username
- password
properties:
username:
type: string
password:
type: string
responses:
200:
description: Login successful
401:
description: Invalid credentials
"""
data = request.get_json()
username = data.get('username')
password = data.get('password')

if not username or not password:
return jsonify({'error': 'Username and password required'}), 400

# Find user by username
user = next((user for user in USERS if user['username'] == username), None)

if not user or user['password'] != password:
return jsonify({'error': 'Invalid username or password'}), 401

return jsonify({
'message': 'Login successful',
'user_id': user['id'],
'username': user['username'],
'email': user['email']
}), 200

# Animal routes
@app.route('/api/animals', methods=['GET'])
def list_animals():
"""
Get all available animals
---
responses:
200:
description: List of available animals
"""
# Filter only available animals
available_animals = [animal for animal in ANIMALS if animal['adoption_status'] == 'Available']
return jsonify(available_animals), 200

@app.route('/api/animals/<int:animal_id>', methods=['GET'])
def animal_details(animal_id):
"""
Get details for a specific animal
---
parameters:
- name: animal_id
in: path
type: integer
required: true
responses:
200:
description: Animal details
404:
description: Animal not found
"""
animal = next((animal for animal in ANIMALS if animal['id'] == animal_id), None)

if not animal:
return jsonify({'error': 'Animal not found'}), 404

return jsonify(animal), 200

@app.route('/api/animals/<int:animal_id>/adopt', methods=['POST'])
def adopt_animal(animal_id):
"""
Adopt an animal
---
parameters:
- name: animal_id
in: path
type: integer
required: true
- in: body
name: adoption
schema:
type: object
required:
- user_id
properties:
user_id:
type: integer
responses:
200:
description: Adoption successful
404:
description: Animal not found
400:
description: Animal not available for adoption
"""
data = request.get_json()
user_id = data.get('user_id')

if not user_id:
return jsonify({'error': 'User ID required'}), 400

# Find the animal
animal_index = next((i for i, animal in enumerate(ANIMALS) if animal['id'] == animal_id), None)

if animal_index is None:
return jsonify({'error': 'Animal not found'}), 404

# Check if animal is available
if ANIMALS[animal_index]['adoption_status'] != 'Available':
return jsonify({'error': 'Animal not available for adoption'}), 400

# Update status to adopted
ANIMALS[animal_index]['adoption_status'] = 'Adopted'

return jsonify({
'message': 'Adoption successful',
'animal': ANIMALS[animal_index]
}), 200

@app.route('/api/animals/search', methods=['GET'])
def search_animals():
"""
Search for animals with filters
---
parameters:
- name: species
in: query
type: string
required: false
- name: min_age
in: query
type: integer
required: false
- name: max_age
in: query
type: integer
required: false
responses:
200:
description: Search results
"""
species = request.args.get('species')
min_age = request.args.get('min_age')
max_age = request.args.get('max_age')

results = ANIMALS.copy()

# Apply filters
if species:
results = [animal for animal in results if animal['species'].lower() == species.lower()]

if min_age:
results = [animal for animal in results if animal['age'] >= int(min_age)]

if max_age:
results = [animal for animal in results if animal['age'] <= int(max_age)]

return jsonify(results), 200

# Serve images of animals
@app.route('/images/<path:filename>')
def serve_image(filename):
return send_from_directory(os.path.join(app.root_path, 'static/images'), filename)

@app.route('/')
def homepage():
return """
<h1>Animal Shelter API</h1>
<p>Welcome to our animal adoption platform!</p>
<a href="/apidocs">View API Documentation</a>
"""
# Add a new pet
@app.route('/api/pets', methods=['POST'])
def add_new_pet():
pet_data = request.get_json()
return add_pet(pet_data)

# Update an existing pet
@app.route('/api/pets/<int:pet_id>', methods=['PUT'])
def update_existing_pet(pet_id):
pet_data = request.get_json()
return update_pet(pet_id, pet_data)

# Delete a pet
@app.route('/api/pets/<int:pet_id>', methods=['DELETE'])
def remove_pet(pet_id):
return delete_pet(pet_id)

# Search for pets
@app.route('/api/pets/search', methods=['GET'])
def search_for_pets():
return search_pets(request.args)

# Reset pets data (for testing)
@app.route('/api/pets/reset', methods=['POST'])
def reset_pets_data():
"""
Reset the pets data to initial state.
---
responses:
200:
description: Pets data reset successfully
"""
reset_pets()
return jsonify({'message': 'Pets data reset successfully'}), 200
if __name__ == '__main__':
app.run(debug=True)
Binary file added backend/main.zip
Binary file not shown.
Loading