Skip to content
6 changes: 5 additions & 1 deletion apps/backend/src/config/typeorm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import { UpdateDonationColTypes1741708808976 } from '../migrations/1741708808976
import { UpdatePantriesTable1738172265266 } from '../migrations/1738172265266-updatePantriesTable';
import { UpdatePantriesTable1739056029076 } from '../migrations/1739056029076-updatePantriesTable';
import { AddOrders1739496585940 } from '../migrations/1739496585940-addOrders';
import { AddManufacturerDetails1743518493960 } from '../migrations/1743518493960-AddManufacturerDetails';
import { AddManufacturerDonationFrequency1743623272909 } from '../migrations/1743623272909-AddManufacturerDonationFrequency';

const config = {
type: 'postgres',
host: `${process.env.DATABASE_HOST}`,
Expand All @@ -33,8 +36,9 @@ const config = {
UpdateDonationColTypes1741708808976,
UpdatePantriesTable1738172265266,
UpdatePantriesTable1739056029076,
UpdateDonations1738697216020,
AddOrders1739496585940,
AddManufacturerDetails1743518493960,
AddManufacturerDonationFrequency1743623272909,
],
};

Expand Down
8 changes: 8 additions & 0 deletions apps/backend/src/donations/donations.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
Patch,
Param,
NotFoundException,
ParseIntPipe,
} from '@nestjs/common';
import { ApiBody } from '@nestjs/swagger';
import { Donation } from './donations.entity';
Expand All @@ -20,6 +21,13 @@ export class DonationsController {
return this.donationService.getAll();
}

@Get('/getManufacturerDonationCount/:manufacturerId')
async getManufacturerDonationCount(
@Param('manufacturerId', ParseIntPipe) manufacturerId: number,
): Promise<number> {
return this.donationService.getManufacturerDonationCount(manufacturerId);
}

@Post('/create')
@ApiBody({
description: 'Details for creating a donation',
Expand Down
7 changes: 7 additions & 0 deletions apps/backend/src/donations/donations.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ export class DonationService {
return this.repo.find();
}

async getManufacturerDonationCount(manufacturerId: number) {
const count = await this.repo.count({
where: { foodManufacturerId: manufacturerId },
});
return count;
}

async create(
foodManufacturerId: number,
dateDonated: Date,
Expand Down
26 changes: 26 additions & 0 deletions apps/backend/src/foodManufacturers/manufacturer.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Controller, Get, Param, ParseIntPipe, Patch } from '@nestjs/common';
import { FoodManufacturer } from './manufacturer.entity';
import { ManufacturerService } from './manufacturer.service';

@Controller('manufacturer')
export class ManufacturerController {
constructor(private manufacturerService: ManufacturerService) {}

@Get('/getDetails/:manufacturerId')
async getManufacturerDetails(
@Param('manufacturerId', ParseIntPipe) manufacturerId: number,
): Promise<FoodManufacturer | null> {
return this.manufacturerService.getDetails(manufacturerId);
}

@Patch('/updateFrequency/:manufacturerId/:frequency')
async updateManufacturerFrequency(
@Param('manufacturerId') manufacturerId: number,
@Param('frequency') frequency: string,
): Promise<FoodManufacturer | null> {
return this.manufacturerService.updateManufacturerFrequency(
manufacturerId,
frequency,
);
}
}
18 changes: 18 additions & 0 deletions apps/backend/src/foodManufacturers/manufacturer.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,22 @@ export class FoodManufacturer {
referencedColumnName: 'id',
})
foodManufacturerRepresentative: User;

@Column({ type: 'varchar', length: 255, nullable: true })
industry: string;

@Column({ type: 'varchar', length: 255, nullable: true })
email: string;

@Column({ type: 'varchar', length: 255, nullable: true })
phone: string;

@Column({ type: 'varchar', length: 255, nullable: true })
address: string;

@Column({ type: 'timestamp', default: () => 'CURRENT_TIMESTAMP' })
signupDate: Date;

@Column({ type: 'varchar', length: 255, nullable: true })
donationFrequency: string;
}
6 changes: 6 additions & 0 deletions apps/backend/src/foodManufacturers/manufacturer.module.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { FoodManufacturer } from './manufacturer.entity';
import { ManufacturerController } from './manufacturer.controller';
import { ManufacturerService } from './manufacturer.service';
import { JwtStrategy } from '../auth/jwt.strategy';
import { AuthService } from '../auth/auth.service';

@Module({
imports: [TypeOrmModule.forFeature([FoodManufacturer])],
controllers: [ManufacturerController],
providers: [ManufacturerService, AuthService, JwtStrategy],
})
export class ManufacturerModule {}
50 changes: 50 additions & 0 deletions apps/backend/src/foodManufacturers/manufacturer.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { FoodManufacturer } from './manufacturer.entity';

@Injectable()
export class ManufacturerService {
constructor(
@InjectRepository(FoodManufacturer)
private repo: Repository<FoodManufacturer>,
) {}

async updateManufacturerFrequency(
manufacturerId: number,
donationFrequency: string,
): Promise<FoodManufacturer | null> {
const manufacturer = await this.repo.findOne({
where: { foodManufacturerId: manufacturerId },
});
if (!manufacturer) {
return null;
}
manufacturer.donationFrequency = donationFrequency;
return this.repo.save(manufacturer);
}

async getDetails(manufacturerId: number): Promise<FoodManufacturer | null> {
if (!manufacturerId || manufacturerId < 1) {
throw new NotFoundException('Invalid manufacturer ID');
}
return await this.repo.findOne({
where: { foodManufacturerId: manufacturerId },
relations: ['foodManufacturerRepresentative'],
select: {
foodManufacturerId: true,
foodManufacturerName: true,
industry: true,
email: true,
phone: true,
address: true,
signupDate: true,
donationFrequency: true,
foodManufacturerRepresentative: {
firstName: true,
lastName: true,
},
},
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { MigrationInterface, QueryRunner } from 'typeorm';

export class AddManufacturerDetails1743518493960 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
ALTER TABLE food_manufacturers
ADD COLUMN industry VARCHAR(255),
ADD COLUMN email VARCHAR(255),
ADD COLUMN phone VARCHAR(255),
ADD COLUMN address VARCHAR(255),
ADD COLUMN signup_date TIMESTAMP NOT NULL DEFAULT NOW();
`);
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
ALTER TABLE food_manufacturers
DROP COLUMN industry,
DROP COLUMN email,
DROP COLUMN phone,
DROP COLUMN address,
DROP COLUMN signup_date;
`);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { MigrationInterface, QueryRunner } from 'typeorm';

export class AddManufacturerDonationFrequency1743623272909
implements MigrationInterface
{
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
ALTER TABLE food_manufacturers
ADD COLUMN donation_frequency VARCHAR(255);
`);
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
ALTER TABLE food_manufacturers
DROP COLUMN donation_frequency;
`);
}
}
35 changes: 34 additions & 1 deletion apps/frontend/src/api/apiClient.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import axios, { type AxiosInstance } from 'axios';
import { Donation, DonationItem, User, Pantry } from 'types/types';
import {
Donation,
DonationItem,
User,
Pantry,
ManufacturerDetails,
} from 'types/types';

const defaultBaseUrl =
import.meta.env.VITE_API_BASE_URL ?? 'http://localhost:3000';
Expand Down Expand Up @@ -31,6 +37,14 @@ export class ApiClient {
.then((response) => response.data);
}

public async getManufacturerDetails(
manufacturerId: number,
): Promise<ManufacturerDetails> {
return this.axiosInstance
.get(`/api/manufacturer/getDetails/${manufacturerId}`)
.then((response) => response.data) as Promise<ManufacturerDetails>;
}

public async updatePantry(
pantryId: number,
decision: 'approve' | 'deny',
Expand All @@ -44,6 +58,14 @@ export class ApiClient {
return this.get(`/api/pantries/${pantryId}`) as Promise<Pantry>;
}

public async getManufacturerDonationCount(
manufacturerId: number,
): Promise<number> {
return this.get(
`/api/donations/getManufacturerDonationCount/${manufacturerId}`,
) as Promise<number>;
}

public async getPantrySSFRep(pantryId: number): Promise<User> {
return this.get(`/api/pantries/${pantryId}/ssf-contact`) as Promise<User>;
}
Expand Down Expand Up @@ -81,6 +103,17 @@ export class ApiClient {
) as Promise<Donation>;
}

public async updateDonationFrequency(
manufacturerId: number,
frequency: string,
body?: unknown,
): Promise<ManufacturerDetails> {
return this.patch(
`/api/manufacturer/updateFrequency/${manufacturerId}/${frequency}`,
body,
) as Promise<ManufacturerDetails>;
}

public async updateDonationItemQuantity(
itemId: number,
body?: unknown,
Expand Down
5 changes: 5 additions & 0 deletions apps/frontend/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import PantryApplication from '@containers/pantryApplication';
import { submitPantryApplicationForm } from '@components/forms/pantryApplicationForm';
import ApprovePantries from '@containers/approvePantries';
import DonationManagement from '@containers/donationManagement';
import FoodManufacturerDashboard from '@containers/foodManufacturerDashboard';

const router = createBrowserRouter([
{
Expand Down Expand Up @@ -73,6 +74,10 @@ const router = createBrowserRouter([
path: '/approve-pantries',
element: <ApprovePantries />,
},
{
path: '/food-manufacturer-dashboard/:manufacturerId',
element: <FoodManufacturerDashboard />,
},
],
},
]);
Expand Down
Loading