{"id":31650672,"url":"https://github.com/8bituhm/uhm-custodian-manager","last_synced_at":"2026-07-10T10:31:04.012Z","repository":{"id":318222408,"uuid":"1068723070","full_name":"8bitUHM/uhm-custodian-manager","owner":"8bitUHM","description":"Internal UH Mānoa Office of Human Resources app to manage and distribute custodial work assignments evenly.","archived":false,"fork":false,"pushed_at":"2026-05-08T18:41:05.000Z","size":10741,"stargazers_count":0,"open_issues_count":12,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-08T20:39:39.386Z","etag":null,"topics":["docker","fastapi","postgresql","react","tailwindcss","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/8bitUHM.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-02T20:11:02.000Z","updated_at":"2026-05-08T18:41:21.000Z","dependencies_parsed_at":"2025-10-05T23:19:22.162Z","dependency_job_id":"0e94f557-9520-4875-8a03-4946903a7dc2","html_url":"https://github.com/8bitUHM/uhm-custodian-manager","commit_stats":null,"previous_names":["8bituhm/uhm-custodian-manager"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/8bitUHM/uhm-custodian-manager","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/8bitUHM%2Fuhm-custodian-manager","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/8bitUHM%2Fuhm-custodian-manager/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/8bitUHM%2Fuhm-custodian-manager/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/8bitUHM%2Fuhm-custodian-manager/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/8bitUHM","download_url":"https://codeload.github.com/8bitUHM/uhm-custodian-manager/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/8bitUHM%2Fuhm-custodian-manager/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35329609,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-10T02:00:06.465Z","response_time":60,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docker","fastapi","postgresql","react","tailwindcss","typescript"],"created_at":"2025-10-07T08:34:35.071Z","updated_at":"2026-07-10T10:31:04.006Z","avatar_url":"https://github.com/8bitUHM.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Custodian Manager Dashboard\n\nA comprehensive custodian management system built with React, TypeScript, Tailwind CSS, FastAPI, and PostgreSQL, all containerized with Docker Compose.\n\n## **Table of Contents**\n1. [Features](#features)\n2. [Tech Stack](#tech-stack)\n3. [Quick Start](#quick-start)\n4. [Development](#development)\n5. [API endpoints](#api-endpoints)\n6. [Database Schema](#database-schema)\n7. [Project Structure](#project-structure)\n8. [Contributing](#contributing)\n9. [License](#license)\n\n---\n\n## Features\n\n- **Dashboard Overview**: Real-time statistics and activity monitoring\n- **Custodian Management**: Add, edit, and track custodian information\n- **Building Management**: Manage buildings and their details\n- **Task Management**: Create, assign, and track cleaning and maintenance tasks\n- **Responsive Design**: Modern UI with Tailwind CSS\n- **RESTful API**: FastAPI backend with automatic documentation\n\n## Tech Stack\n\n### Frontend\n- React 18 with TypeScript\n- Next.js 14\n- Tailwind CSS for styling\n- Lucide React for icons\n- Axios for API calls\n\n### Backend\n- FastAPI with Python 3.11\n- SQLAlchemy ORM\n- PostgreSQL database\n- Pydantic for data validation\n- Alembic for database migrations\n\n### Infrastructure\n- Docker \u0026 Docker Compose\n- PostgreSQL 15\n- Multi-container setup\n\n## Quick Start\n\n### **Prerequisites**\nEnsure you have **Python 3.8+** installed. You can check your Python version with:\n\n```sh\npython --version\n```\n\nor\n\n```sh\npython3 --version\n```\n\nIf Python is not installed, download and install it from [python.org](https://www.python.org/downloads/).\n\nNode is also needed for this project. Download and install node from [here](https://nodejs.org/en/download) if it is not installed.\n\nShould have [**Docker Desktop**](https://www.docker.com/get-started/) installed. If you are unsure what docker desktop is, please refer to [Section 4-6 of Infrastructure \u0026 DevOps](https://8bithawaii.org/learning/lessons/infrastructure-devops).\n\n1. **Clone the repository**\n   ```bash\n   git clone https://github.com/8bitUHM/uhm-custodian-manager.git\n   cd uhm-custodian-manager\n   ```\n\n2. **Start up docker desktop**\n\n3. **Start the application**\n   ```bash\n   docker-compose up --build\n   ```\n   If you are running the application on macOS\n   ```bash\n   docker compose up --build\n   ```\n\n5. **Access the application**\n   - Frontend: http://localhost:3000\n   - Backend API: http://localhost:8000\n   - API Documentation: http://localhost:8000/docs\n\n### Seeding the database\n\nThe repository ships with `backend/seed_data.json`, a snapshot of the BGM custodial\norg chart extracted from `EMPLOYEE GROUP INFO.xlsx` (3 Janitor Supervisor IIs,\n18 Janitor IIIs, and 126 Janitor IIs, organized by wing and work group).\n\nAfter the stack is up, populate the database with:\n\n```bash\ndocker exec custodian_backend python seed.py\n```\n\nThe seeder is idempotent: it clears `custodians`, `j3`, and `supervisors` before\ninserting, so it is safe to re-run. Buildings and tasks are not touched.\n\n## Development\n\n### Pulling from main (after PR is merged)\nMake sure to re-run `docker-compose up --build` to get the project running. \nFor frontend, you will need to run `npm install` before running the compose.\n\n### Running Individual Services\n\n**Frontend only:**\n```bash\ncd frontend\nnpm install\nnpm run dev\n```\n\n**Backend only:**\n```bash\ncd backend\npip install -r requirements.txt\nuvicorn main:app --reload\n```\n\n**Database only:**\n```bash\ndocker-compose up db\n```\n\n### Environment Variables\n\nCopy `env.example` to `.env` and modify as needed:\n```bash\ncp env.example .env\n```\n\n### How to add a new page and route entry point\n1. Make a new folder of what the page will be in the src\\app folder\n2.\tMake a tsx file that's named \"page.tsx\" in the same folder that you created\n3.\tAdd your content on there\n4.\tWhatever is the folder name will represent the link name\nex: If i make a folder named \"about-me\" in the src\\app folder and I make a page.tsx in the \"about-me\" folder, the link that will show the content within the same folder will be localhost:3000/about-me\n\n## API Endpoints\n\n### Dashboard\n- `GET /api/dashboard/stats` - Get dashboard statistics\n\n### Custodians\n- `GET /api/custodians/` - List all custodians\n- `POST /api/custodians/` - Create new custodian\n- `GET /api/custodians/{id}` - Get custodian by ID\n\n### Buildings\n- `GET /api/buildings/` - List all buildings\n- `POST /api/buildings/` - Create new building\n- `GET /api/buildings/{id}` - Get building by ID\n\n### Tasks\n- `GET /api/tasks/` - List all tasks\n- `POST /api/tasks/` - Create new task\n- `GET /api/tasks/{id}` - Get task by ID\n\n## Database Schema\n\n### Custodians\n- Personal information (name, email, phone)\n- Employee ID and status\n- Hire date and timestamps\n\n### Buildings\n- Building details (name, address, code)\n- Floor count and description\n- Active status\n\n### Tasks\n- Task details (title, description, priority)\n- Assignment to custodians and buildings\n- Status tracking and scheduling\n\n## Project Structure\n\n```\nuhm-custodian-manager/\n├── frontend/                 # Next.js React application\n│   ├── src/\n│   │   ├── app/             # App router pages\n│   │   └── components/      # Reusable components\n│   ├── Dockerfile\n│   └── package.json\n├── backend/                  # FastAPI application\n│   ├── main.py              # FastAPI app and routes\n│   ├── models.py            # SQLAlchemy models\n│   ├── schemas.py           # Pydantic schemas\n│   ├── crud.py              # Database operations\n│   ├── database.py          # Database configuration\n│   ├── Dockerfile\n│   └── requirements.txt\n├── docker-compose.yml       # Multi-container setup\n├── init.sql                 # Database initialization\n└── README.md\n```\n\n## Alembic Migrations (Backend)\n\nWhen working on the `models.py`, you will have to create an alembic migration to reflect changes in the model (model = table in psql). \n\nMake sure to be in your virtual environment\n\nCreate migration: `alembic revision --autogenerate`\n\n- this should automatically create changes to reflect changes in your new file in the `versions`\n\nSample Migration File: \n```python\n\"\"\"empty message\n\nRevision ID: ---\nRevises: ---\nCreate Date: ---\n\n\"\"\"\nfrom typing import Sequence, Union\n\nfrom alembic import op\nfrom sqlalchemy import Column, String, Integer, Text, Boolean, DateTime, Enum, ForeignKey\nfrom sqlalchemy.sql import func\nfrom models import TaskStatus\n\n# revision identifiers, used by Alembic.\nrevision: str = '7b6c3da95734'\ndown_revision: Union[str, None] = None\nbranch_labels: Union[str, Sequence[str], None] = None\ndepends_on: Union[str, Sequence[str], None] = None\n\n\ndef upgrade() -\u003e None:\n    # ### commands auto generated by Alembic - please adjust! ###\n   \n   # Reflect new changes here\n   op.create_table(\n      'buildings',\n      Column('id', Integer, primary_key=True, ...)\n   )\n    \n    # ### end Alembic commands ###\n\n\ndef downgrade() -\u003e None:\n    # ### commands auto generated by Alembic - please adjust! ###\n    # Undo changes here\n\n    op.drop_table(\n      'buildings',\n      Column('id', Integer, primary_key=True, ...)\n    )\n    # ### end Alembic commands ###\n```\n\nPush new migration: `docker exec custodian_backend alembic upgrade rev_id`\n\n- If you leave out `docker exec` it will fail the migration to the docker db. \n\n- You don't need all of the rev_id, usually you can use the first 2-5 characters. \n\nAlembic is similar to git development (pull, push, commit) so you will maybe encounter problems in Alembic that are like git (Alembic has branches!). \n\n**Reference**: [Alembic Docs](https://alembic.sqlalchemy.org/en/latest/tutorial.html)\n\n## Contributing\n\n1. Fork the repository\n2. Create a feature branch\n3. Make your changes\n4. Test thoroughly\n5. Submit a pull request\n\n## License\n\nThis project is licensed under the MIT License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F8bituhm%2Fuhm-custodian-manager","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F8bituhm%2Fuhm-custodian-manager","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F8bituhm%2Fuhm-custodian-manager/lists"}