forked from Code-4-Community/scaffolding
-
Notifications
You must be signed in to change notification settings - Fork 0
Confirm food delivered and Request Forms Dashboard #21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
31 commits
Select commit
Hold shift + click to select a range
09f77a7
Initial commit for this branch
dburkhart07 4d303ea
food request modal and button, updated form contents
Juwang110 28951ee
Updated design for request forms page
dburkhart07 0fc781d
remove unecessary form data, made component into a button to be used …
Juwang110 fb3fc5f
Merge branch 'main' into food-request-form
Juwang110 d6ccd89
backend post form route working, created food requests backend folder…
Juwang110 11730b3
Renamed frontend component to RequestForms (Admin dashboard of all ac…
dburkhart07 6c78018
Completed frontend, just need to incorporate backend APIs into it
dburkhart07 22b7000
fixed submit button orientation, added description to form, deleted o…
Juwang110 ffae96e
Updated dashboard to properly get the requests by pantryId in database
dburkhart07 dc088a8
remove old form route
Juwang110 bac85b2
Updated API endpoint for confirm delivery and added previous order fu…
dburkhart07 d3e98c2
fix form submission bug
Juwang110 3fcced8
Fixed confirming delivery dates, previous requests, and smaller featu…
dburkhart07 5ce06a1
Final push for branch
dburkhart07 2389fb3
Fixed final aspects of deliveryConfirmation
dburkhart07 bd48e43
adding api body for documentation in swagger
Juwang110 067c220
Pulled changes from food-request
dburkhart07 9e93647
Created base64 encoding for uploaded photos
dburkhart07 e14c427
Logic for AWS S3 photo uploads and paths saved to database
dburkhart07 70c240b
Fixed PR suggested changes
dburkhart07 3c9498d
Finished PR changes
dburkhart07 5f229b1
Finalized AWS photo uploads
dburkhart07 549f512
Cleaned up code for consistency
dburkhart07 f16ad86
Fixing styling of request form page
dburkhart07 a1ae283
Fixed formattings
dburkhart07 b285c5e
Fixed code format
dburkhart07 c2c433c
Fixed backend alerting
dburkhart07 806ea34
Removed unwanted binary files
dburkhart07 6f0e232
Removed unwanted binary files
dburkhart07 9361a32
Fixed optional photo uploading
dburkhart07 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| import { Global, Module } from '@nestjs/common'; | ||
| import { AWSS3Service } from './aws-s3.service'; | ||
|
|
||
| @Global() | ||
| @Module({ | ||
| imports: [], | ||
| providers: [AWSS3Service], | ||
| exports: [AWSS3Service], | ||
| }) | ||
| export class AWSS3Module {} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| import { Injectable } from '@nestjs/common'; | ||
| import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3'; | ||
|
|
||
| @Injectable() | ||
| export class AWSS3Service { | ||
| private client: S3Client; | ||
| private readonly bucket: string; | ||
| private readonly region: string; | ||
|
|
||
| constructor() { | ||
| this.region = process.env.AWS_REGION || 'us-east-2'; | ||
| this.bucket = process.env.AWS_BUCKET_NAME; | ||
| if (!this.bucket) { | ||
| throw new Error('AWS_BUCKET_NAME is not defined'); | ||
| } | ||
| this.client = new S3Client({ | ||
| region: this.region, | ||
| credentials: { | ||
| accessKeyId: process.env.AWS_ACCESS_KEY_ID, | ||
| secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY, | ||
| }, | ||
| }); | ||
| } | ||
|
|
||
| async upload(files: Express.Multer.File[]): Promise<string[]> { | ||
| const uploadedFileUrls: string[] = []; | ||
| try { | ||
| for (const file of files) { | ||
| const fileName = file.originalname; | ||
|
|
||
| const command = new PutObjectCommand({ | ||
| Bucket: this.bucket, | ||
| Key: fileName, | ||
| Body: file.buffer, | ||
| ContentType: file.mimetype || 'application/octet-stream', | ||
| }); | ||
|
|
||
| await this.client.send(command); | ||
|
|
||
| const url = `https://${this.bucket}.s3.${this.region}.amazonaws.com/${fileName}`; | ||
| uploadedFileUrls.push(url); | ||
| } | ||
| return uploadedFileUrls; | ||
| } catch (error) { | ||
| throw new Error('File upload to AWS failed'); | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,145 @@ | ||
| import { | ||
| Controller, | ||
| Get, | ||
| Param, | ||
| ParseIntPipe, | ||
| Post, | ||
| Body, | ||
| UploadedFiles, | ||
| UseInterceptors, | ||
| } from '@nestjs/common'; | ||
| import { ApiBody } from '@nestjs/swagger'; | ||
| import { RequestsService } from './request.service'; | ||
| import { FoodRequest } from './request.entity'; | ||
| import { AWSS3Service } from '../aws/aws-s3.service'; | ||
| import { FilesInterceptor } from '@nestjs/platform-express'; | ||
| import * as multer from 'multer'; | ||
|
|
||
| @Controller('requests') | ||
| // @UseInterceptors() | ||
| export class FoodRequestsController { | ||
| constructor( | ||
| private requestsService: RequestsService, | ||
| private awsS3Service: AWSS3Service, | ||
| ) {} | ||
|
|
||
| @Get('/:pantryId') | ||
| async getAllPantryRequests( | ||
| @Param('pantryId', ParseIntPipe) pantryId: number, | ||
| ): Promise<FoodRequest[]> { | ||
| return this.requestsService.find(pantryId); | ||
| } | ||
|
|
||
| @Post('/create') | ||
| @ApiBody({ | ||
| description: 'Details for creating a food request', | ||
| schema: { | ||
| type: 'object', | ||
| properties: { | ||
| pantryId: { type: 'integer', example: 1 }, | ||
| requestedSize: { type: 'string', example: 'Medium (5-10 boxes)' }, | ||
| requestedItems: { | ||
| type: 'array', | ||
| items: { type: 'string' }, | ||
| example: ['Rice Noodles', 'Quinoa'], | ||
| }, | ||
| additionalInformation: { | ||
| type: 'string', | ||
| nullable: true, | ||
| example: 'Urgent request', | ||
| }, | ||
| status: { type: 'string', example: 'pending' }, | ||
| fulfilledBy: { type: 'integer', nullable: true, example: null }, | ||
| dateReceived: { | ||
| type: 'string', | ||
| format: 'date-time', | ||
| nullable: true, | ||
| example: null, | ||
| }, | ||
| feedback: { type: 'string', nullable: true, example: null }, | ||
| photos: { | ||
| type: 'array', | ||
| items: { type: 'string' }, | ||
| nullable: true, | ||
| example: [], | ||
| }, | ||
| }, | ||
| }, | ||
| }) | ||
| async createRequest( | ||
| @Body() | ||
| body: { | ||
| pantryId: number; | ||
| requestedSize: string; | ||
| requestedItems: string[]; | ||
| additionalInformation: string; | ||
| status: string; | ||
| fulfilledBy: number; | ||
| dateReceived: Date; | ||
| feedback: string; | ||
| photos: string[]; | ||
| }, | ||
| ): Promise<FoodRequest> { | ||
| return this.requestsService.create( | ||
| body.pantryId, | ||
| body.requestedSize, | ||
| body.requestedItems, | ||
| body.additionalInformation, | ||
| body.status, | ||
| body.fulfilledBy, | ||
| body.dateReceived, | ||
| body.feedback, | ||
| body.photos, | ||
| ); | ||
| } | ||
|
|
||
| @Post('/:requestId/confirm-delivery') | ||
| @ApiBody({ | ||
| description: 'Details for a confirmation form', | ||
| schema: { | ||
| type: 'object', | ||
| properties: { | ||
| dateReceived: { | ||
| type: 'string', | ||
| format: 'date-time', | ||
| nullable: true, | ||
| example: new Date().toISOString(), | ||
| }, | ||
| feedback: { | ||
| type: 'string', | ||
| nullable: true, | ||
| example: 'Wonderful shipment!', | ||
| }, | ||
| photos: { | ||
| type: 'array', | ||
| items: { type: 'string' }, | ||
| nullable: true, | ||
| example: [], | ||
| }, | ||
| }, | ||
| }, | ||
| }) | ||
| @UseInterceptors( | ||
| FilesInterceptor('photos', 10, { storage: multer.memoryStorage() }), | ||
| ) | ||
| async confirmDelivery( | ||
| @Param('requestId', ParseIntPipe) requestId: number, | ||
| @Body() body: { dateReceived: string; feedback: string }, | ||
| @UploadedFiles() photos?: Express.Multer.File[], | ||
| ): Promise<FoodRequest> { | ||
| const formattedDate = new Date(body.dateReceived); | ||
| if (isNaN(formattedDate.getTime())) { | ||
| throw new Error('Invalid date format for deliveryDate'); | ||
| } | ||
|
|
||
| const uploadedPhotoUrls = | ||
| photos && photos.length > 0 ? await this.awsS3Service.upload(photos) : []; | ||
|
|
||
| return this.requestsService.updateDeliveryDetails( | ||
| requestId, | ||
| formattedDate, | ||
| body.feedback, | ||
| uploadedPhotoUrls, | ||
| ); | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| import { | ||
| Entity, | ||
| Column, | ||
| PrimaryGeneratedColumn, | ||
| CreateDateColumn, | ||
| } from 'typeorm'; | ||
|
|
||
| @Entity('food_requests') | ||
| export class FoodRequest { | ||
| @PrimaryGeneratedColumn({ name: 'request_id' }) | ||
| requestId: number; | ||
|
|
||
| @Column({ name: 'pantry_id', type: 'int' }) | ||
| pantryId: number; | ||
|
|
||
| @Column({ name: 'requested_size', type: 'varchar', length: 50 }) | ||
| requestedSize: string; | ||
|
|
||
| @Column({ name: 'requested_items', type: 'text', array: true }) | ||
| requestedItems: string[]; | ||
|
|
||
| @Column({ name: 'additional_information', type: 'text', nullable: true }) | ||
| additionalInformation: string; | ||
|
|
||
| @CreateDateColumn({ | ||
| name: 'requested_at', | ||
| type: 'timestamp', | ||
| default: () => 'NOW()', | ||
| }) | ||
| requestedAt: Date; | ||
|
|
||
| @Column({ name: 'status', type: 'varchar', length: 25, default: 'pending' }) | ||
| status: string; | ||
|
|
||
| @Column({ name: 'fulfilled_by', type: 'int', nullable: true }) | ||
| fulfilledBy: number; | ||
|
|
||
| @Column({ name: 'date_received', type: 'timestamp', nullable: true }) | ||
| dateReceived: Date; | ||
|
|
||
| @Column({ name: 'feedback', type: 'text', nullable: true }) | ||
| feedback: string; | ||
|
|
||
| @Column({ name: 'photos', type: 'text', array: true, nullable: true }) | ||
| photos: string[]; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| import { Module } from '@nestjs/common'; | ||
| import { TypeOrmModule } from '@nestjs/typeorm'; | ||
| import { FoodRequestsController } from './request.controller'; | ||
| import { FoodRequest } from './request.entity'; | ||
| import { RequestsService } from './request.service'; | ||
| import { JwtStrategy } from '../auth/jwt.strategy'; | ||
| import { AuthService } from '../auth/auth.service'; | ||
| import { AWSS3Module } from '../aws/aws-s3.module'; | ||
| import { MulterModule } from '@nestjs/platform-express'; | ||
|
|
||
| @Module({ | ||
| imports: [ | ||
| AWSS3Module, | ||
| MulterModule.register({ dest: './uploads' }), | ||
| TypeOrmModule.forFeature([FoodRequest]), | ||
| ], | ||
| controllers: [FoodRequestsController], | ||
| providers: [RequestsService, AuthService, JwtStrategy], | ||
| }) | ||
| export class RequestsModule {} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| import { Injectable, NotFoundException } from '@nestjs/common'; | ||
| import { InjectRepository } from '@nestjs/typeorm'; | ||
| import { Repository } from 'typeorm'; | ||
| import { FoodRequest } from './request.entity'; | ||
|
|
||
| @Injectable() | ||
| export class RequestsService { | ||
| constructor( | ||
| @InjectRepository(FoodRequest) private repo: Repository<FoodRequest>, | ||
| ) {} | ||
|
|
||
| async create( | ||
| pantryId: number, | ||
| requestedSize: string, | ||
| requestedItems: string[], | ||
| additionalInformation: string | null, | ||
| status: string = 'pending', | ||
| fulfilledBy: number | null, | ||
| dateReceived: Date | null, | ||
| feedback: string | null, | ||
| photos: string[] | null, | ||
| ) { | ||
| const foodRequest = this.repo.create({ | ||
| pantryId, | ||
| requestedSize, | ||
| requestedItems, | ||
| additionalInformation, | ||
| status, | ||
| fulfilledBy, | ||
| dateReceived, | ||
| feedback, | ||
| photos, | ||
| }); | ||
|
|
||
| return await this.repo.save(foodRequest); | ||
| } | ||
|
|
||
| async find(pantryId: number) { | ||
| if (!pantryId || pantryId < 1) { | ||
| throw new NotFoundException('Invalid pantry ID'); | ||
| } | ||
| return await this.repo.find({ where: { pantryId } }); | ||
| } | ||
|
|
||
| async updateDeliveryDetails( | ||
| requestId: number, | ||
| deliveryDate: Date, | ||
| feedback: string, | ||
| photos: string[], | ||
| ): Promise<FoodRequest> { | ||
| const request = await this.repo.findOne({ where: { requestId } }); | ||
|
|
||
| if (!request) { | ||
| throw new NotFoundException('Invalid request ID'); | ||
| } | ||
|
|
||
| request.feedback = feedback; | ||
| request.dateReceived = deliveryDate; | ||
| request.photos = photos; | ||
| request.status = 'fulfilled'; | ||
|
|
||
| return await this.repo.save(request); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.