Animal Rescue Dashboard
An interactive data dashboard built for the fictional animal rescue organization Grazioso Salvare, combining MongoDB-backed animal records, dynamic filtering, visual analytics, and geographic mapping to support rescue-specific decision making.
Turning shelter data into an operational dashboard.
This application was developed for Grazioso Salvare, an animal rescue organization focused on identifying animals suited for Water Rescue, Mountain or Wilderness Rescue, and Disaster or Individual Tracking.
Rather than presenting shelter records as a static dataset, the dashboard turns those records into an interactive interface where users can filter animals according to rescue requirements and inspect the resulting data through several synchronized views.
MongoDB provides the data-storage layer, while Python, Pandas, Dash, Plotly Express, and Dash Leaflet form the application and visualization layers.
Designing the interface around real filtering goals.
The dashboard is organized around three rescue categories, each representing a different operational need.
WATER RESCUE
Filters the available animal records according to characteristics relevant to water-rescue work.
MOUNTAIN / WILDERNESS
Produces a dataset targeted toward animals suited for wilderness-oriented rescue operations.
DISASTER / TRACKING
Supports exploration of animals associated with disaster-response or individual-tracking requirements.
RESET
Restores the unfiltered dataset so users can return to the full collection without reloading the application.
Connecting persisted data to multiple interactive views.
The application follows a simple data pipeline where shelter records move from source data into MongoDB and are then transformed for use by the dashboard.
Moving structured shelter records into MongoDB.
Pandas was used to read the animal shelter dataset and transform its rows into dictionary-style records that could be inserted into MongoDB.
df = pd.read_csv("aac_shelter_outcomes.csv")
data_dict = df.to_dict("records")
collection.insert_many(data_dict)
This approach provided a clear transition from tabular CSV data to document-based database records.
The project also required working with missing values and standardizing location information so downstream dashboard components could operate on reliable data.
Using a flexible document model for animal records.
MongoDB served as the primary persistence layer for the rescue records. Its document model provided a practical fit for animal data containing attributes such as breed, name, rescue-related characteristics, and location coordinates.
PyMongo provided the connection between the Python application and MongoDB, allowing the project to work with the dataset through database operations rather than treating the CSV file as the final application data source.
CREATE
Import animal records into the MongoDB collection.
READ
Retrieve records used by the dashboard and rescue filters.
UPDATE
Work with stored records through database-backed operations.
DELETE
Support the full set of CRUD concepts required for managing persistent records.
Giving users several ways to understand the same data.
The dashboard presents animal information through multiple coordinated components rather than relying on a single visualization.
RESCUE FILTERS
Radio controls let users switch between rescue categories or reset the dashboard.
DATA TABLE
A paginated and sortable table supports detailed inspection of individual animal records.
PIE CHART
Breed distribution is summarized visually for the active result set.
GEOLOCATION MAP
Animal coordinates are translated into map markers with contextual information.
Synchronizing multiple outputs from one user action.
Dash callbacks form the connection between user interaction and dashboard state.
When a user selects a rescue category, the callback determines which dataset should be active and uses that result to rebuild the table, chart, and map.
@app.callback(
[Output('datatable-id', 'data'),
Output('graph-id', 'figure'),
Output('map-id', 'children')],
[Input('filter-type', 'value')]
)
def update_dashboard(filter_type):
if filter_type == 'reset':
data = df
else:
data = get_filtered_data(filter_type)
fig = px.pie(
data,
names='breed',
title='Preferred Animals'
)
markers = [
dl.Marker(
position=[
row['location_lat'],
row['location_long']
],
children=[
dl.Tooltip(row['breed']),
dl.Popup(row['name'])
]
)
for _, row in data.iterrows()
]
return data.to_dict('records'), fig, markers
The important architectural idea is that the three visual components do not maintain independent filter states. They are all derived from the same filtered dataset.
Preserving access to the underlying records.
Charts provide summaries, but operational users may still need the actual records behind those summaries.
The interactive data table provides that detailed view while supporting pagination and sorting. This lets the dashboard balance high-level visual analysis with record-level inspection.
Summarizing breed distribution within filtered results.
Plotly Express is used to create a pie chart from the currently active dataset.
Because the chart is generated from filtered records rather than a static copy of the original data, its distribution changes when the user selects a different rescue category.
That makes the visualization useful as a comparative tool: the user can see how the breed composition differs across operational rescue requirements.
Adding geography as another dimension of the dataset.
Dash Leaflet translates latitude and longitude values into geographic markers so users can inspect where filtered animal records are located.
Each generated marker includes contextual information through tooltips and popups, including details such as breed and animal name.
Keeping the dataset clean enough for every component to trust it.
One challenge was that several downstream features depended on consistent data.
Missing values or inconsistent location information could affect the table, visualization, or map differently. Cleaning and standardizing the data therefore became an important part of making the overall interface reliable.
MISSING VALUES
Incomplete data needed to be handled before it reached visualization logic.
LOCATION FIELDS
Geographic values needed sufficient consistency for map markers.
FILTER OUTPUT
Rescue filters needed to produce predictable subsets of the dataset.
COMPONENT SYNC
Every visual component needed to represent the same active filter state.
Seeing the dashboard change across rescue modes.
These views show the interface in its default state and after applying each rescue-specific filter.
Designing data tools for users who should not need to understand the database.
One of the important lessons from this project was that the technical structure of a data application should remain largely invisible to the person using it.
A user should not need to understand MongoDB queries, Pandas transformations, or callback mechanics to answer a practical question about the rescue dataset.
Connecting database development, data processing, and interface design.
This project strengthened my understanding of how data moves through an application from storage to presentation.
MongoDB provided persistence, Pandas supported data transformation, Dash connected user interaction to application state, Plotly summarized the active data visually, and Leaflet added geographic context.
Working across those layers reinforced the importance of keeping the data consistent throughout the application. A filter was not complete simply because the table changed; every dependent visualization had to update from the same source of truth.
A complete data-driven interface built around operational questions.
The finished dashboard combines persistence, querying, transformation, visualization, mapping, and interactive UI behavior into one application.
The project gave me practical experience building an application in which database decisions, data quality, backend logic, visualization, and user experience all affect one another.