,
- private emailsService: EmailsService,
- ) {}
-
- // Example endpoint for email sending (DO NOT DEPLOY THIS)
- /*
- async sendTestEmail(recipient: string) {
- const imageRes = await fetch('https://placehold.co/200x200/png');
- const imageBuffer = Buffer.from(await imageRes.arrayBuffer());
-
- const dto: SendEmailDTO = {
- toEmail: recipient,
- ccEmails: ['cc@example.com'],
- bccEmails: ['bcc@example.com'],
- subject: 'Test email',
- bodyHtml: 'This is a test email sent from UsersService.
',
- attachments: [
- {
- filename: 'sample.png',
- content: imageBuffer,
- },
- ],
- };
- return this.emailsService.sendEmail(dto);
- }
- */
-
- async create(
- email: string,
- firstName: string,
- lastName: string,
- status: Status = Status.STANDARD,
- ) {
- const userId = (await this.repo.count()) + 1;
- const user = this.repo.create({
- id: userId,
- status,
- firstName,
- lastName,
- email,
- });
-
- return this.repo.save(user);
- }
-
- findOne(id: number) {
- if (!id) {
- return null;
- }
-
- return this.repo.findOneBy({ id });
- }
-
- find(email: string) {
- return this.repo.find({ where: { email } });
- }
-
- async update(id: number, attrs: Partial) {
- const user = await this.findOne(id);
-
- if (!user) {
- throw new NotFoundException('User not found');
- }
-
- Object.assign(user, attrs);
-
- return this.repo.save(user);
- }
-
- async remove(id: number) {
- const user = await this.findOne(id);
-
- if (!user) {
- throw new NotFoundException('User not found');
- }
-
- return this.repo.remove(user);
- }
-}
diff --git a/apps/backend/src/volunteers/volunteers.controller.ts b/apps/backend/src/volunteers/volunteers.controller.ts
index 3efd63ade..d2c246fc8 100644
--- a/apps/backend/src/volunteers/volunteers.controller.ts
+++ b/apps/backend/src/volunteers/volunteers.controller.ts
@@ -1,7 +1,15 @@
import { Controller } from '@nestjs/common';
import { VolunteersService } from './volunteers.service';
+// @ApiTags('Volunteers')
+// @ApiBearerAuth()
@Controller('volunteers')
export class VolunteersController {
constructor(private volunteersService: VolunteersService) {}
+
+ // Example endpoint
+ // @Get('/:userId')
+ // async getUser(@Param('userId', ParseIntPipe) userId: number): Promise {
+ // return this.usersService.findOne(userId);
+ // }
}
diff --git a/apps/backend/src/volunteers/volunteers.service.ts b/apps/backend/src/volunteers/volunteers.service.ts
index df28421df..1c6f17a61 100644
--- a/apps/backend/src/volunteers/volunteers.service.ts
+++ b/apps/backend/src/volunteers/volunteers.service.ts
@@ -9,4 +9,21 @@ export class VolunteersService {
@InjectRepository(FosterVolunteer)
private repo: Repository,
) {}
+
+ // Example service functions
+ // find(email: string) {
+ // return this.repo.find({ where: { email } });
+ // }
+
+ // async update(id: number, attrs: Partial) {
+ // const user = await this.findOne(id);
+
+ // if (!user) {
+ // throw new NotFoundException('User not found');
+ // }
+
+ // Object.assign(user, attrs);
+
+ // return this.repo.save(user);
+ // }
}
From 36f72250eb85ddf80f62eab6c69830d471b9171d Mon Sep 17 00:00:00 2001
From: Dalton Burkhart <137221425+dburkhart07@users.noreply.github.com>
Date: Mon, 14 Sep 2026 00:43:32 -0400
Subject: [PATCH 08/20] Update README.md
---
README.md | 4 ----
1 file changed, 4 deletions(-)
diff --git a/README.md b/README.md
index 2653c6b12..0d8230c64 100644
--- a/README.md
+++ b/README.md
@@ -97,10 +97,6 @@ The backend can expose [Swagger UI](https://github.com/swagger-api/swagger-ui) (
**Turn it off:** Unset `SWAGGER_ENABLED` or set it to `false`.
-**TL TODOS:**
-1. In [`apps/backend/src/main.ts`](apps/backend/src/main.ts), replace `[YOUR_APP_NAME]` and other `[TL]` strings, adjust `.addTag()` entries to match your controllers,
-2. Add `@ApiBearerAuth()` onto the controller or handler for specifically protected routes. `addBearerAuth()` only states that the application supports authentication via HTTP Bearer in the Authorization header, it doesn't mark specific routes as protected. [Learn more](https://docs.nestjs.com/openapi/security#bearer-authentication)
-
**Decorators to know as you add routes!**
(import from `@nestjs/swagger`):
- `@ApiProperty()` / `@ApiPropertyOptional()`: on top of DTO fields
From 280fb3701577a62a16404ae0673b63ad1d71ec68 Mon Sep 17 00:00:00 2001
From: Dalton Burkhart
Date: Mon, 14 Sep 2026 00:47:46 -0400
Subject: [PATCH 09/20] Fixed env variables
---
apps/backend/src/config/typeorm.ts | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/apps/backend/src/config/typeorm.ts b/apps/backend/src/config/typeorm.ts
index 967c82205..fba681c15 100644
--- a/apps/backend/src/config/typeorm.ts
+++ b/apps/backend/src/config/typeorm.ts
@@ -6,11 +6,11 @@ import 'pg';
const config = {
type: 'postgres',
- host: `${process.env.DATABASE_HOST}`,
- port: parseInt(`${process.env.DATABASE_PORT}`, 10),
- database: `${process.env.DATABASE_NAME}`,
- username: `${process.env.DATABASE_USERNAME}`,
- password: `${process.env.DATABASE_PASSWORD}`,
+ host: `${process.env.NX_DB_HOST}`,
+ port: parseInt(`${process.env.NX_DB_PORT}`, 10),
+ database: `${process.env.NX_DB_DATABASE}`,
+ username: `${process.env.NX_DB_USERNAME}`,
+ password: `${process.env.NX_DB_PASSWORD}`,
autoLoadEntities: true,
synchronize: false,
namingStrategy: new PluralNamingStrategy(),
From 422462e7dff7dc35ecff699870bb5e9b99a51077 Mon Sep 17 00:00:00 2001
From: Dalton Burkhart <137221425+dburkhart07@users.noreply.github.com>
Date: Mon, 14 Sep 2026 00:48:55 -0400
Subject: [PATCH 10/20] Update README.md
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 0d8230c64..af6b04583 100644
--- a/README.md
+++ b/README.md
@@ -27,7 +27,7 @@ docker run --name scaffolding-db \
**Option B — pgAdmin / existing Postgres install:**
-Create a new database (e.g. `jumpstart`) through pgAdmin or `psql`.
+Create a new database (e.g. `mspca`) through pgAdmin or `psql`.
**Configure connection strings:**
From 996ef9492db3b59dc540004eba0733cf5d606ce5 Mon Sep 17 00:00:00 2001
From: Dalton Burkhart
Date: Mon, 14 Sep 2026 00:53:13 -0400
Subject: [PATCH 11/20] Added CI jobs into README
---
README.md | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/README.md b/README.md
index af6b04583..bec0e4aee 100644
--- a/README.md
+++ b/README.md
@@ -89,6 +89,38 @@ To run both the frontend and backend with one command:
nx run-many -t serve -p frontend backend
```
+## CI (GitHub Actions)
+
+On every push and pull request, GitHub Actions runs:
+
+- Prettier — checks formatting
+- Lint - checks the linter
+- Backend tests — runs Jest test suites
+
+### Local commands
+
+Prettier:
+
+```
+yarn prettier:check # verify formatting
+yarn prettier:write # fix formatting
+```
+
+Lint:
+
+```
+yarn lint:check # runs linter
+yarn lint # fixes linting issues
+```
+
+Backend tests:
+
+```
+yarn test
+```
+
+The locally hosted frontend and backend will update live as you make changes to the code. Happy coding!
+
## Swagger
The backend can expose [Swagger UI](https://github.com/swagger-api/swagger-ui) (built from an OpenAPI document via [`@nestjs/swagger`](https://docs.nestjs.com/openapi/introduction)) so you can browse and try HTTP routes without reading controller code first.
From 2ca87253fbc39d0094ad9ab3e9f453b7f7e80895 Mon Sep 17 00:00:00 2001
From: Dalton Burkhart <137221425+dburkhart07@users.noreply.github.com>
Date: Mon, 14 Sep 2026 00:54:10 -0400
Subject: [PATCH 12/20] Fix typo in README.md for Lint formatting
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index bec0e4aee..e9e22fd4a 100644
--- a/README.md
+++ b/README.md
@@ -94,7 +94,7 @@ nx run-many -t serve -p frontend backend
On every push and pull request, GitHub Actions runs:
- Prettier — checks formatting
-- Lint - checks the linter
+- Lint — checks the linter
- Backend tests — runs Jest test suites
### Local commands
From 6ae75c272d5ef7fd0ef5657ea3b0f42acc28d7d3 Mon Sep 17 00:00:00 2001
From: Dalton Burkhart
Date: Mon, 14 Sep 2026 21:08:52 -0400
Subject: [PATCH 13/20] Added id validation util function
---
apps/backend/src/utils/validation.utils.spec.ts | 14 ++++++++++++++
apps/backend/src/utils/validation.utils.ts | 7 +++++++
2 files changed, 21 insertions(+)
create mode 100644 apps/backend/src/utils/validation.utils.spec.ts
create mode 100644 apps/backend/src/utils/validation.utils.ts
diff --git a/apps/backend/src/utils/validation.utils.spec.ts b/apps/backend/src/utils/validation.utils.spec.ts
new file mode 100644
index 000000000..6b3908403
--- /dev/null
+++ b/apps/backend/src/utils/validation.utils.spec.ts
@@ -0,0 +1,14 @@
+import { BadRequestException } from '@nestjs/common';
+import { validateId } from './validation.utils';
+
+describe('validateId', () => {
+ it('should not throw an error for a valid ID', () => {
+ expect(() => validateId(5, 'User')).not.toThrow();
+ });
+
+ it('should throw BadRequestException for ID < 1', () => {
+ expect(() => validateId(0, 'User')).toThrow(
+ new BadRequestException('Invalid User ID'),
+ );
+ });
+});
diff --git a/apps/backend/src/utils/validation.utils.ts b/apps/backend/src/utils/validation.utils.ts
new file mode 100644
index 000000000..5c4f14a78
--- /dev/null
+++ b/apps/backend/src/utils/validation.utils.ts
@@ -0,0 +1,7 @@
+import { BadRequestException } from '@nestjs/common';
+
+export function validateId(id: number, entityName: string): void {
+ if (!id || id < 1) {
+ throw new BadRequestException(`Invalid ${entityName} ID`);
+ }
+}
From a82852aaa77f34ac2f07111bb17f1db3db31f313 Mon Sep 17 00:00:00 2001
From: Dalton Burkhart
Date: Mon, 14 Sep 2026 21:29:13 -0400
Subject: [PATCH 14/20] Added volunteer coordinator relationship
---
.../src/coordinators/coordinators.entity.ts | 9 ++++++++-
.../backend/src/volunteers/volunteers.entity.ts | 17 ++++++++++++++++-
2 files changed, 24 insertions(+), 2 deletions(-)
diff --git a/apps/backend/src/coordinators/coordinators.entity.ts b/apps/backend/src/coordinators/coordinators.entity.ts
index c0940f946..1ce7a3c06 100644
--- a/apps/backend/src/coordinators/coordinators.entity.ts
+++ b/apps/backend/src/coordinators/coordinators.entity.ts
@@ -1,5 +1,6 @@
-import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
+import { Entity, PrimaryGeneratedColumn, Column, OneToMany } from 'typeorm';
import { Homebase } from '../types';
+import { FosterVolunteer } from '../volunteers/volunteers.entity';
@Entity('foster_coordinators')
export class FosterCoordinator {
@@ -31,4 +32,10 @@ export class FosterCoordinator {
@Column({ type: 'boolean' })
active!: boolean;
+
+ @OneToMany(
+ () => FosterVolunteer,
+ (volunteer) => volunteer.assignedCoordinator,
+ )
+ assignedVolunteers!: FosterVolunteer[];
}
diff --git a/apps/backend/src/volunteers/volunteers.entity.ts b/apps/backend/src/volunteers/volunteers.entity.ts
index c49284a9d..45633aad2 100644
--- a/apps/backend/src/volunteers/volunteers.entity.ts
+++ b/apps/backend/src/volunteers/volunteers.entity.ts
@@ -1,6 +1,13 @@
-import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
+import {
+ Entity,
+ PrimaryGeneratedColumn,
+ Column,
+ ManyToOne,
+ JoinColumn,
+} from 'typeorm';
import { Homebase } from '../types';
import { FosterType } from './volunteers.types';
+import { FosterCoordinator } from '../coordinators/coordinators.entity';
@Entity('foster_volunteers')
export class FosterVolunteer {
@@ -60,4 +67,12 @@ export class FosterVolunteer {
@Column({ type: 'boolean' })
active!: boolean;
+
+ @ManyToOne(
+ () => FosterCoordinator,
+ (coordinator) => coordinator.assignedVolunteers,
+ { nullable: true },
+ )
+ @JoinColumn({ name: 'assigned_coordinator_id' })
+ assignedCoordinator!: FosterCoordinator | null;
}
From 8048a768888c4996a3ee13d59fc783270327bd40 Mon Sep 17 00:00:00 2001
From: Dalton Burkhart <137221425+dburkhart07@users.noreply.github.com>
Date: Thu, 17 Sep 2026 23:05:27 -0400
Subject: [PATCH 15/20] Ddb/test branch (#1)
* Added comment
* Fixed pre-push
---
.husky/pre-push | 3 ---
apps/backend/src/types.ts | 1 +
2 files changed, 1 insertion(+), 3 deletions(-)
diff --git a/.husky/pre-push b/.husky/pre-push
index 834ceb651..34edbdddd 100755
--- a/.husky/pre-push
+++ b/.husky/pre-push
@@ -1,6 +1,3 @@
-#!/usr/bin/env sh
-. "$(dirname -- "$0")/_/husky.sh"
-
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
diff --git a/apps/backend/src/types.ts b/apps/backend/src/types.ts
index 3c667a091..828006066 100644
--- a/apps/backend/src/types.ts
+++ b/apps/backend/src/types.ts
@@ -1,3 +1,4 @@
+// All commonly shared types go in here
export enum Homebase {
BOSTON = 'Boston',
CAPE_COD = 'Cape Cod',
From 1842757b4682b62a0128911deea0faa7eb2f5d34 Mon Sep 17 00:00:00 2001
From: Dalton Burkhart <137221425+dburkhart07@users.noreply.github.com>
Date: Sun, 20 Sep 2026 18:58:10 -0400
Subject: [PATCH 16/20] Update PostgreSQL setup instructions in README
Removed Docker setup instructions for PostgreSQL and updated password note.
---
README.md | 15 +--------------
1 file changed, 1 insertion(+), 14 deletions(-)
diff --git a/README.md b/README.md
index e9e22fd4a..67697cf69 100644
--- a/README.md
+++ b/README.md
@@ -14,19 +14,6 @@ You can optionally install `nx` globally with `npm install -g nx` - if you don't
This project uses PostgreSQL. You'll need a running Postgres instance before starting the backend.
-**Option A — Docker (recommended for local dev):**
-
-```bash
-docker run --name scaffolding-db \
- -e POSTGRES_USER=postgres \
- -e POSTGRES_PASSWORD=postgres \
- -e POSTGRES_DB=[DB NAME HERE] \
- -p 5432:5432 \
- -d postgres:15
-```
-
-**Option B — pgAdmin / existing Postgres install:**
-
Create a new database (e.g. `mspca`) through pgAdmin or `psql`.
**Configure connection strings:**
@@ -41,7 +28,7 @@ cp example.env .env
NX_DB_HOST=localhost
NX_DB_PORT=5432
NX_DB_USERNAME=postgres
-NX_DB_PASSWORD=postgres
+NX_DB_PASSWORD=postgres (replace this with your actual PGAdmin4 password)
NX_DB_DATABASE=[DB NAME HERE]
```
From 74dac85084f1cb530809bcd1fa21f4eb34cda30c Mon Sep 17 00:00:00 2001
From: Dalton Burkhart <137221425+dburkhart07@users.noreply.github.com>
Date: Mon, 21 Sep 2026 01:48:34 -0400
Subject: [PATCH 17/20] Delete .github/CODEOWNERS
---
.github/CODEOWNERS | 1 -
1 file changed, 1 deletion(-)
delete mode 100644 .github/CODEOWNERS
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
deleted file mode 100644
index ee529b859..000000000
--- a/.github/CODEOWNERS
+++ /dev/null
@@ -1 +0,0 @@
-* @maxn990
From 2bed4ed1184a4f70c46a80ecd5c3895318fdd6c1 Mon Sep 17 00:00:00 2001
From: Dalton Burkhart <137221425+dburkhart07@users.noreply.github.com>
Date: Mon, 21 Sep 2026 01:48:48 -0400
Subject: [PATCH 18/20] Delete .github/dependabot.yml
---
.github/dependabot.yml | 14 --------------
1 file changed, 14 deletions(-)
delete mode 100644 .github/dependabot.yml
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
deleted file mode 100644
index ef97a9eaf..000000000
--- a/.github/dependabot.yml
+++ /dev/null
@@ -1,14 +0,0 @@
-# To get started with Dependabot version updates, you'll need to specify which
-# package ecosystems to update and where the package manifests are located.
-# Please see the documentation for all configuration options:
-# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
-
-version: 2
-updates:
- - package-ecosystem: "npm" # See documentation for possible values
- directory: "/" # Location of package manifests
- schedule:
- interval: "weekly"
- day: "monday"
- time: "02:34"
- timezone: "America/New_York"
From 91a46b2ca123503ab434cf929e0f24ebc3e6b5da Mon Sep 17 00:00:00 2001
From: Shreeya Adhikari
Date: Thu, 24 Sep 2026 15:16:55 -0400
Subject: [PATCH 19/20] created update volunteer dto
---
.../src/volunteers/update-volunteer.dto.ts | 61 +++++++++++++++++++
1 file changed, 61 insertions(+)
create mode 100644 apps/backend/src/volunteers/update-volunteer.dto.ts
diff --git a/apps/backend/src/volunteers/update-volunteer.dto.ts b/apps/backend/src/volunteers/update-volunteer.dto.ts
new file mode 100644
index 000000000..a1317a24a
--- /dev/null
+++ b/apps/backend/src/volunteers/update-volunteer.dto.ts
@@ -0,0 +1,61 @@
+import { FosterCoordinator as number } from '../coordinators/coordinators.entity';
+import { Homebase } from '../types';
+import { FosterType } from './volunteers.types';
+import { IsOptional, IsString, IsNumber, IsBoolean, IsEnum } from 'class-validator';
+
+
+export class UpdateVolunteerDto {
+
+@IsOptional()
+@IsNumber()
+volunteerId?: number;
+@IsOptional()
+@IsString()
+firstName?: string;
+@IsOptional()
+@IsString()
+lastName?: string;
+@IsOptional()
+@IsString()
+phone?: string;
+@IsOptional()
+@IsString()
+secondaryPhone?: string;
+@IsOptional()
+@IsString()
+email?: string;
+@IsOptional()
+@IsString()
+address?: string;
+@IsOptional()
+@IsString()
+city?: string;
+@IsOptional()
+@IsString()
+zipcode?: string;
+@IsOptional()
+@IsEnum(Homebase)
+homebase?: Homebase;
+@IsOptional()
+@IsString()
+residentAnimals?: string;
+@IsOptional()
+@IsString()
+notes?: string;
+@IsOptional()
+@IsEnum(FosterType)
+fosterType?: FosterType;
+@IsOptional()
+@IsBoolean()
+completedCanineTraining?: boolean;
+@IsOptional()
+@IsBoolean()
+mostRecentWaiverSigned?: boolean;
+@IsOptional()
+@IsBoolean()
+active?: boolean;
+@IsOptional()
+@IsNumber()
+assignedCoordinatorId?: number;
+
+}
\ No newline at end of file
From dc55c8951c48f5652748a012b55eeb5c71d79a41 Mon Sep 17 00:00:00 2001
From: Shreeya Adhikari
Date: Sat, 26 Sep 2026 14:02:55 -0400
Subject: [PATCH 20/20] created deny match dto and added service logic
---
apps/backend/src/matches/deny-match.dto.ts | 7 +++++++
apps/backend/src/matches/matches.service.ts | 22 +++++++++++++++++++++
2 files changed, 29 insertions(+)
create mode 100644 apps/backend/src/matches/deny-match.dto.ts
diff --git a/apps/backend/src/matches/deny-match.dto.ts b/apps/backend/src/matches/deny-match.dto.ts
new file mode 100644
index 000000000..b4a15ed80
--- /dev/null
+++ b/apps/backend/src/matches/deny-match.dto.ts
@@ -0,0 +1,7 @@
+import { IsNotEmpty, IsString } from 'class-validator';
+
+export class DenyMatchDto {
+ @IsNotEmpty()
+ @IsString()
+ deniedReason!: string;
+}
\ No newline at end of file
diff --git a/apps/backend/src/matches/matches.service.ts b/apps/backend/src/matches/matches.service.ts
index e91ccaf65..fab8ef157 100644
--- a/apps/backend/src/matches/matches.service.ts
+++ b/apps/backend/src/matches/matches.service.ts
@@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Match } from './matches.entity';
+import { MatchStatus } from './matches.types';
@Injectable()
export class MatchesService {
@@ -9,4 +10,25 @@ export class MatchesService {
@InjectRepository(Match)
private repo: Repository,
) {}
+
+ async approveMatch(id: number) {
+ const match = await this.repo.findOneBy({ matchId: id });
+ if (!match) {
+ return null;
+ }
+
+ match.status = MatchStatus.COMPLETE;
+ return this.repo.save(match);
+ }
+
+ async denyMatch(id: number, deniedReason: string) {
+ const match = await this.repo.findOneBy({ matchId: id });
+ if (!match) {
+ return null;
+ }
+
+ match.status = MatchStatus.DENIED;
+ match.deniedReason = deniedReason;
+ return this.repo.save(match);
+ }
}