Skip to content

Commit

Permalink
Merge pull request #20 from CSE2102-Spring25/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
ris20010 authored Apr 11, 2025
2 parents 9bf5bfb + fe97eb7 commit d23bf5f
Show file tree
Hide file tree
Showing 9 changed files with 647 additions and 0 deletions.
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

0 comments on commit d23bf5f

Please sign in to comment.