Skip to content
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

View one form page #39

Merged
merged 8 commits into from
Apr 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
70 changes: 63 additions & 7 deletions apps/backend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions apps/backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@
"ion-js": "^4.3.0",
"jsbi": "^3.2.5",
"source-map-support": "^0.5.21",
"uuid": "^9.0.0",
"zod": "^3.20.6"
},
"devDependencies": {
"@tsconfig/node18": "^1.0.1",
"@types/aws-lambda": "^8.10.110",
"@types/node": "^18.13.0",
"@types/uuid": "^9.0.1",
"aws-sdk-client-mock": "^2.0.0",
"jest": "^29.2.1",
"quicktype": "^21.0.12",
Expand Down
10 changes: 9 additions & 1 deletion apps/backend/src/db/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,17 @@ export async function insertDocument(
}

export async function fetchDocuments() {
return await qldbDriver.executeLambda(async (txn) => {
const result = await txn.execute(`SELECT * from ${tableName}`);
return result.getResultList();
});
}

export async function fetchDocumentById(id: string) {
return await qldbDriver.executeLambda(async (txn) => {
const result = await txn.execute(
`SELECT * FROM ${tableName}`
`SELECT * FROM ${tableName} where id = ?`,
id
);
return result.getResultList();
});
Expand Down
50 changes: 50 additions & 0 deletions apps/backend/src/handlers/getFormById.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { APIGatewayEvent } from 'aws-lambda';
import { createTableIfNotExists } from '../db/createTable.js';
import { fetchDocumentById } from '../db/utils.js';

/**
* An HTTP get method to get all forms from the QLDB table.
*/
export const getFormByIdHandler = async (event: APIGatewayEvent) => {
const headers = {
'Access-Control-Allow-Headers': 'Content-Type, Access-Control-Allow-Origin',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET',
};

if (event.httpMethod !== 'GET') {
return {
statusCode: 400,
headers,
body: `getMethod only accepts GET method, you tried: ${event.httpMethod} method.`,
};
}
// All log statements are written to CloudWatch
console.info('received:', event);

try {
await createTableIfNotExists();
const id = event.pathParameters!.id!;
const form = await fetchDocumentById(id);

const response = {
statusCode: 200,
headers,
body: JSON.stringify(form),
};

// All log statements are written to CloudWatch
console.info(
`response from: ${event.path} statusCode: ${response.statusCode}`
);

return response;
} catch (error) {
console.error('error accessing database', error);
return {
statusCode: 400,
headers,
body: 'error',
};
}
};
3 changes: 2 additions & 1 deletion apps/backend/src/handlers/putForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { APIGatewayEvent } from 'aws-lambda';
import { createTableIfNotExists } from '../db/createTable.js';
import { insertDocument } from '../db/utils.js';
import { formSchema } from '../schema/schema.js';

import { v4 as uuidv4 } from 'uuid';
/**
* An HTTP post method to add one form to the QLDB table.
*/
Expand All @@ -27,6 +27,7 @@ export const putFormHandler = async (event: APIGatewayEvent) => {
let form;
try {
form = formSchema.parse(JSONbody);
form.id = uuidv4();
} catch (error) {
return {
statusCode: 400,
Expand Down
9 changes: 8 additions & 1 deletion apps/backend/src/schema/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const addressSchema = z.object({
street: z.string().min(1),
city: z.string().min(1),
state: z.string().min(1),
zipcode: z.number(),
zipcode: z.string().length(5),
});

// Regex to check for phone numbers formatted with `-`, ' ', and '.' separators,
Expand All @@ -15,6 +15,11 @@ const phoneNumber = z.string().regex(phoneNumberRegex);
// Schema to convert input to javascript date object
const dateSchema = z.coerce.date();

const adminNoteSchema = z.object({
note: z.string(),
updatedAt: dateSchema,
});

// Part of form to be filled out by the child's parent/legal guardian
const guardianFormSchema = z.object({
childsName: z.string().min(1),
Expand Down Expand Up @@ -52,6 +57,8 @@ const medicalFormSchema = z.object({
});

export const formSchema = z.object({
id: z.string(),
guardianForm: guardianFormSchema,
medicalForm: medicalFormSchema,
adminNotes: adminNoteSchema.array(),
});
18 changes: 18 additions & 0 deletions apps/backend/template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,24 @@ Resources:
Method: GET
RestApiId: !Ref ApiGateway

getFormByIdFunction:
Type: AWS::Serverless::Function
Properties:
Handler: dist/handlers/getFormById.getFormByIdHandler
Runtime: nodejs18.x
Architectures:
- x86_64
MemorySize: 128
Timeout: 100
Description: An http get method to get a form with a certain ID.
Role: !GetAtt QLDBSendCommandRole.Arn
Events:
Api:
Type: Api
Properties:
Path: /form/{id}
Method: GET
RestApiId: !Ref ApiGateway
# This is a Lambda function config associated with the source code: putForm.ts
putFormFunction:
Type: AWS::Serverless::Function
Expand Down
9 changes: 9 additions & 0 deletions apps/frontend/src/app/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { RequireAuth } from '../components/auth/RequireAuth';
import ViewFormsList from '../components/ViewFormsList';
import NotFoundPage from '../pages/404';
import FormPage from '../pages/FormPage';
import OneFormPage from '../pages/OneFormPage';

Amplify.configure(awsExports);

Expand All @@ -25,6 +26,14 @@ function ConstellationRoutes() {
</RequireAuth>
}
/>
<Route
path="/form/:id"
element={
<RequireAuth>
<OneFormPage />
</RequireAuth>
}
/>
<Route path="*" element={<NotFoundPage />} />
</Routes>
</BrowserRouter>
Expand Down
10 changes: 10 additions & 0 deletions apps/frontend/src/components/ErrorMessage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Text } from '@chakra-ui/react';

interface ErrorMessageProps {
message: string;
}
export const ErrorMessage: React.FC<ErrorMessageProps> = ({ message }) => (
<Text align="center" fontSize="xl">
Error: {message}
</Text>
);
2 changes: 1 addition & 1 deletion apps/frontend/src/components/form/GrantForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ const GrantForm: React.FC = () => {
/>

<FormField
inputVariant="number"
inputVariant="text"
name="guardianForm.address.zipcode"
displayName="Zip Code"
isRequired
Expand Down
2 changes: 1 addition & 1 deletion apps/frontend/src/components/form/MedicalForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ const MedicalForm: React.FC = () => {
/>

<FormField
inputVariant="number"
inputVariant="text"
name="medicalForm.address.zipcode"
displayName="Zip Code"
isRequired
Expand Down
19 changes: 19 additions & 0 deletions apps/frontend/src/components/viewForm/FieldView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Container, Heading, Text } from '@chakra-ui/react';

interface FieldViewProps {
fieldName: string;
value: string;
}
export const FieldView: React.FC<FieldViewProps> = ({ fieldName, value }) => (
<Container padding="0" width="fit-content" margin="16px 56px 16px 0px">
<Heading
size="xs"
color="gray.500"
textTransform="uppercase"
paddingBottom="2px"
>
{fieldName}
</Heading>
<Text fontSize="xl">{value}</Text>
</Container>
);
Loading