Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
e9ae82f
feat: add chapter name filtering to nonprofits query
amandayu255 Dec 14, 2025
69c72c6
feat: add chapter names filtering to nonprofits query
amandayu255 Dec 14, 2025
95c6306
feat: add function to retrieve chapter IDs by names
amandayu255 Dec 14, 2025
96557af
Merge branch 'develop' into feature/61-filter-nonprofits
soramicha Dec 17, 2025
6a2acdd
feat: add nonprofitChapterProjects query to retrieve projects by nonp…
amandayu255 Dec 18, 2025
cd1b889
feat: add NonprofitChapterProject type and query for chapter projects
amandayu255 Dec 18, 2025
43f65c6
feat: implement Docker-based test database setup for isolated testing
amandayu255 Dec 18, 2025
23afe67
ran prettier formatting
amandayu255 Dec 18, 2025
f2cd0ca
Merge branch 'develop' into feature/61-filter-nonprofits
amandayu255 Dec 18, 2025
7807039
feat: enhance filtering logic for nonprofits with dynamic conditions
amandayu255 Dec 18, 2025
4f57c72
feat: add support for pagination in nonprofit queries
amandayu255 Dec 27, 2025
3929bfd
feat: add NonprofitChapterInfo type and update Nonprofit schema to in…
amandayu255 Dec 27, 2025
4ebcc75
feat: refactor nonprofit resolvers to simplify logic and improve perf…
amandayu255 Dec 27, 2025
5d128b4
fix: add missing newline at end of nonprofit schema file
amandayu255 Dec 27, 2025
7a791c3
feat: enhance nonprofit filtering logic with dynamic join conditions
amandayu255 Dec 27, 2025
9c5e368
feat: add support for advanced filtering options in nonprofit queries
amandayu255 Dec 27, 2025
1d3988d
Merge branch 'develop' into feature/61-filter-nonprofits
amandayu255 Dec 27, 2025
dd59d92
fix: ensure proper formatting in configuration files and add missing …
amandayu255 Dec 27, 2025
4d684b8
fix: improve type safety in nonprofit resolvers by refining chapter f…
amandayu255 Dec 27, 2025
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
73 changes: 38 additions & 35 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,37 +1,40 @@
{
"root": true,
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 2020,
"sourceType": "module"
},
"plugins": ["@typescript-eslint"],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"prettier"
],
"ignorePatterns": [
"node_modules/**",
"*.config.mts",
"prisma/**",
"legacy**",
"generated/**"
],
"rules": {
"@typescript-eslint/no-unused-expressions": [
"error",
{ "allowShortCircuit": true, "allowTernary": true, "allowTaggedTemplates": true }
]
},
"overrides": [
{
"files": ["tests/**/*.ts", "tests/**/*.js"],
"rules": {
"@typescript-eslint/no-require-imports": "off",
"@typescript-eslint/no-unused-expressions": "off"
}
}
"root": true,
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 2020,
"sourceType": "module"
},
"plugins": ["@typescript-eslint"],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"prettier"
],
"ignorePatterns": [
"node_modules/**",
"*.config.mts",
"prisma/**",
"legacy**",
"generated/**"
],
"rules": {
"@typescript-eslint/no-unused-expressions": [
"error",
{
"allowShortCircuit": true,
"allowTernary": true,
"allowTaggedTemplates": true
}
]
}

},
"overrides": [
{
"files": ["tests/**/*.ts", "tests/**/*.js"],
"rules": {
"@typescript-eslint/no-require-imports": "off",
"@typescript-eslint/no-unused-expressions": "off"
}
}
]
}
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,4 @@ jobs:

- name: Stop test database
if: always()
run: docker compose down -v
run: docker compose down -v
98 changes: 49 additions & 49 deletions .github/workflows/develop_operations-api.yml
Original file line number Diff line number Diff line change
@@ -1,49 +1,49 @@
# Docs for the Azure Web Apps Deploy action: https://github.com/Azure/webapps-deploy
# More GitHub Actions for Azure: https://github.com/Azure/actions
name: Build and deploy Node.js app to Azure Web App - operations-api
on:
push:
branches:
- develop
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read #This is required for actions/checkout
steps:
- uses: actions/checkout@v4
- name: Set up Node.js version
uses: actions/setup-node@v3
with:
node-version: '24.x'
- name: Upload artifact for deployment job
uses: actions/upload-artifact@v4
with:
name: node-app
path: .
deploy:
runs-on: ubuntu-latest
needs: build
steps:
- name: Download artifact from build job
uses: actions/download-artifact@v4
with:
name: node-app
- name: 'Deploy to Azure Web App'
id: deploy-to-webapp
uses: azure/webapps-deploy@v3
with:
app-name: 'operations-api'
slot-name: 'Production'
package: .
publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_FD3F1E6E02E34288BF14598390887468 }}
# Docs for the Azure Web Apps Deploy action: https://github.com/Azure/webapps-deploy
# More GitHub Actions for Azure: https://github.com/Azure/actions

name: Build and deploy Node.js app to Azure Web App - operations-api

on:
push:
branches:
- develop
workflow_dispatch:

jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read #This is required for actions/checkout

steps:
- uses: actions/checkout@v4

- name: Set up Node.js version
uses: actions/setup-node@v3
with:
node-version: '24.x'

- name: Upload artifact for deployment job
uses: actions/upload-artifact@v4
with:
name: node-app
path: .

deploy:
runs-on: ubuntu-latest
needs: build

steps:
- name: Download artifact from build job
uses: actions/download-artifact@v4
with:
name: node-app

- name: 'Deploy to Azure Web App'
id: deploy-to-webapp
uses: azure/webapps-deploy@v3
with:
app-name: 'operations-api'
slot-name: 'Production'
package: .
publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_FD3F1E6E02E34288BF14598390887468 }}
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,8 +230,8 @@ Command to enter in terminal to access tables:

- docker compose exec -T test-db psql -U postgres -d test_db
- \dt
- SQL commands such as (SELECT * FROM volunteers;)
- SQL commands such as (SELECT \* FROM volunteers;)

To pause test, insert this: await new Promise(() => {});

It helps you see when data is created in the local database!
It helps you see when data is created in the local database!
6 changes: 3 additions & 3 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ services:
POSTGRES_PASSWORD: test_password
POSTGRES_DB: test_db
ports:
- "5433:5432" # Map to port 5433 to avoid conflicts with local PostgreSQL
- '5433:5432' # Map to port 5433 to avoid conflicts with local PostgreSQL
volumes:
- test-db-data:/var/lib/postgresql/data
- ./db-init:/docker-entrypoint-initdb.d # Initialization scripts
- ./db-init:/docker-entrypoint-initdb.d # Initialization scripts
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres -d test_db"]
test: ['CMD-SHELL', 'pg_isready -U postgres -d test_db']
interval: 5s
timeout: 5s
retries: 5
Expand Down
63 changes: 59 additions & 4 deletions src/api/graphql/resolvers/nonprofits.resolvers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,50 @@ import {
getNonprofitsWithFilters,
updateNonprofit,
updateNonprofitSchema,
getChapterIdsByNames,
} from '../../../core';
import { GraphQLError } from 'graphql';
import { z } from 'zod';
import type {
StatusType,
NonprofitSortOption,
} from '../../../core/services/nonprofits.service';
import { prisma } from '../../../config/database';
import { status_type } from '@prisma/client';

// Infer TypeScript types directly from your Zod schemas
type CreateNonprofitInput = z.infer<typeof createNonprofitSchema>;
type UpdateNonprofitInput = z.infer<typeof updateNonprofitSchema>;

interface NonprofitsQueryArgs {
chapterIds?: string[];
chapterNames?: string[];
statuses?: StatusType[];
sort?: NonprofitSortOption[];
}

export const nonprofitResolvers = {
Query: {
nonprofits: (
nonprofits: async (
_parent: unknown,
{ chapterIds, statuses, sort }: NonprofitsQueryArgs
{ chapterIds, chapterNames, statuses, sort }: NonprofitsQueryArgs
) => {
return getNonprofitsWithFilters({ chapterIds, statuses, sort });
let resolvedChapterIds = chapterIds;

if (
(!resolvedChapterIds || resolvedChapterIds.length === 0) &&
chapterNames?.length
) {
resolvedChapterIds = await getChapterIdsByNames(chapterNames);
if (!resolvedChapterIds.length) return [];
}

return getNonprofitsWithFilters({
chapterIds: resolvedChapterIds,
statuses,
sort,
});
},

nonprofit: async (_parent: unknown, { id }: { id: string }) => {
const nonprofit = await getNonprofitById(id);
if (!nonprofit) {
Expand All @@ -48,6 +66,41 @@ export const nonprofitResolvers = {
return nonprofit;
},
},

Nonprofit: {
chapters: async (parent: { nonprofit_id: string }) => {
const rows = await prisma.nonprofit_chapter_project.findMany({
where: { nonprofit_id: parent.nonprofit_id },
select: {
project_status: true,
chapters: {
select: {
chapter_id: true,
name: true,
},
},
},
orderBy: { created_at: 'desc' },
});

return rows
.filter(
(
r
): r is {
project_status: status_type;
chapters: { chapter_id: string; name: string };
} => r.chapters !== null
)
.map((r) => ({
chapter_id: r.chapters.chapter_id,
chapter_name: r.chapters.name,
project_status:
r.project_status === status_type.ACTIVE ? 'ACTIVE' : 'INACTIVE',
}));
},
},

Mutation: {
createNonprofit: (
_parent: unknown,
Expand All @@ -56,6 +109,7 @@ export const nonprofitResolvers = {
const validatedInput = createNonprofitSchema.parse(input);
return createNonprofit(validatedInput);
},

updateNonprofit: (
_parent: unknown,
{
Expand All @@ -66,6 +120,7 @@ export const nonprofitResolvers = {
const validatedInput = updateNonprofitSchema.parse(input);
return updateNonprofit(nonprofit_id, validatedInput);
},

deleteNonprofit: (_parent: unknown, { id }: { id: string }) => {
return deleteNonprofit(id);
},
Expand Down
11 changes: 11 additions & 0 deletions src/api/graphql/schemas/nonprofits.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ export const nonprofitSchemaString = `
STATUS
}

type NonprofitChapterInfo {
chapter_id: ID!
chapter_name: String!
project_status: StatusType!
}

type Nonprofit {
nonprofit_id: ID!
name: String!
Expand All @@ -16,14 +22,19 @@ export const nonprofitSchemaString = `
created_at: String!
updated_at: String!
status: StatusType!

# chapter + project status info (pulled internally from nonprofit_chapter_project)
chapters: [NonprofitChapterInfo!]!
}

type Query {
nonprofits(
chapterIds: [ID!]
chapterNames: [String!]
statuses: [StatusType!]
sort: [NonprofitSortOption!]
): [Nonprofit!]!

nonprofit(id: ID!): Nonprofit
}

Expand Down
Loading