Skip to content

Commit

Permalink
[NMP-62]: Frontend init (#66)
Browse files Browse the repository at this point in the history
  • Loading branch information
dallascrichmond authored Nov 15, 2024
1 parent a7fa68c commit 184bdbc
Show file tree
Hide file tree
Showing 136 changed files with 1,755 additions and 15,740 deletions.
222 changes: 38 additions & 184 deletions frontend/README.md
Original file line number Diff line number Diff line change
@@ -1,196 +1,50 @@
# Welcome to QuackStack 'Better Berries' Frontend 🚀
# React + TypeScript + Vite

## About the Frontend
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.

Our frontend is a Vite React project written in TypeScript. This is a mobile first, intuitive and modern interface where users can easily manage their farm nutrient calculations on the go.
Currently, two official plugins are available:

## Project Description
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh

The 'Better Berries' is a Progressive Web Application that helps farmers to calculate accurate and precise nutrients needed for their crops.
This is an excerpt of the original workflow of the Sustainment's team Nutrient Management Program. ([NMP](https://nmp.apps.nrs.gov.bc.ca/))
## Expanding the ESLint configuration

## Frameworks / Library
If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:

- [Vite](https://vitejs.dev/)
- [React](https://react.dev/)
- [TypeScript](https://www.typescriptlang.org/)
- [Design Tokens](https://www.npmjs.com/package/@bcgov/design-tokens?activeTab=readme)
- [Emotion](https://emotion.sh/docs/introduction)
- Configure the top-level `parserOptions` property like this:

## Run Locally

Clone the project

```bash
git clone https://github.com/bcgov/nr-sustainment-capstone-2024.git
```

Go to the project directory

```bash
cd frontend
```

Install dependencies

```bash
npm install
```

Start docker compose

```bash
docker-compose up
```

You can also add --build to build docker-compose.yml and --watch in order to control CLI

For deleting volumes of docker

```bash
docker-compose down -v
```

## Running Tests

Test are using [Vitest](https://vitest.dev/) which is a Vite-native testing framework that is based from [Jest](https://jestjs.io/). More information about testing will be in the [Wiki](https://github.com/bcgov/nr-sustainment-capstone-2024/blob/main/README.md)

```bash
npm run test
```

## Usage/Examples

### Component Imports

ESlint will enforce component imports to be at the bottom of other imports.

```javascript
import axios from 'axios' // Needs to be at top of Component, or ESlint will complain.
import Component from 'my-project'

const function = () => {block of code} // ESlint enforces ES6, because author loves ES6.
```

### Testing imports

Frontend Testing is testing what a block of code displays in the Web Application. Therefore, we need **jest-dom** to assert state of the DOM.

```javascript
import '@testing-library/jest-dom'; // Asserts state of DOM, toBeInTheDocument

developers.forEach((developer:DeveloperInterface) => {
expect(screen.getByText(developer.first_name)).toBeInTheDocument();
expect(screen.getByText(developer.last_name)).toBeInTheDocument();
});
```js
export default tseslint.config({
languageOptions: {
// other options...
parserOptions: {
project: ['./tsconfig.node.json', './tsconfig.app.json'],
tsconfigRootDir: import.meta.dirname,
},
},
})
```

### Interface Imports
- Replace `tseslint.configs.recommended` to `tseslint.configs.recommendedTypeChecked` or `tseslint.configs.strictTypeChecked`
- Optionally add `...tseslint.configs.stylisticTypeChecked`
- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and update the config:

To ensure clarity and understandability with other developers, interface/types can be created since we are using TypeScript.
```js
// eslint.config.js
import react from 'eslint-plugin-react'

```javascript
export interface DeveloperInterface {
id: number;
first_name: string;
last_name: string;
}
export default tseslint.config({
// Set the react version
settings: { react: { version: '18.3' } },
plugins: {
// Add the react plugin
react,
},
rules: {
// other rules...
// Enable its recommended rules
...react.configs.recommended.rules,
...react.configs['jsx-runtime'].rules,
},
})
```

This is where you import it and use it as a type/interface.

```javascript
const developers: Array<DeveloperInterface> = [
{ id: 1, first_name: 'G', last_name: 'Damaso' },
{ id: 2, first_name: 'K', last_name: 'Caparas' },
{ id: 3, first_name: 'S', last_name: 'Spy' },
];
```

### Design tokens and Emotion Styled components

We need to follow BC's Styling guide, for this purpose, we're using BC Design Tokens.
To get some more flexibility and provide a fresh and modern design, we will also use Emotion.
The are imported in a `*.style.tsx` file, then Design tokens are used whenever possible, and emotion on should add some flare on top of it.

Here's a simple example of design tokens being used:

```TypeScript
import styled from '@emotion/styled';
import * as tokens from '@bcgov/design-tokens/js';

const StyledFooter = styled.footer`
display: flex;
flex-direction: column;
position: fixed;
bottom: 0;
color: ${tokens.typographyColorPlaceholder};
font-size: ${tokens.typographyRegularLabel};
margin-bottom: 36px;
p {
margin: 0;
}
a {
color: ${tokens.typographyColorLink};
}
`;

export default StyledFooter;


> [!NOTE]
> The stylings in here are not perfect and can be improved further. I left some comments along the way to improve it in the future.
```

### Formik && Yup

Formik is being used to handle our InputModule forms. It is coupled with Yup for building validation schemas.
Formik helps a lot in managing input field states and updating data. It simplifies code and improves functionality.
There are some custom components such as Field and ErrorMessage provided by it which implements these functionalities.
A good example is our Name input field for our FarmInformation InputModule, where a custom submission handler is being provided with some initial values and a yup validationSchema:

```TypeScript
const initialValues = {
FarmName: farmDetails.FarmName,
Year: farmDetails.Year,
FarmRegion: farmDetails.FarmRegion,
};

const validationSchema = Yup.object().shape({
FarmName: Yup.string().max(24).required('Required'),
Year: Yup.number().min(1900).max(2099).required('Required'),
FarmRegion: Yup.string().required('Required'),
});

...

<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={onSubmit}
>
<Form>
<StyledFarmInfo>
<label htmlFor="FarmName">
<p>Name</p>
</label>
<Field
id="FarmName"
name="FarmName"
type="text"
/>
<ErrorMessage name="FarmName" />

...

</StyledFarmInfo>
</Form>
</Formik>

...
```

<!-- Here's a simple example using emotion: -->
<!-- ```TypeScript -->

<!-- ``` -->
14 changes: 4 additions & 10 deletions frontend/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,12 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0"
/>
<title>Better Berries</title>
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React + TS</title>
</head>

<body>
<div id="root"></div>
<script
type="module"
src="/src/main.tsx"
></script>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
Loading

0 comments on commit 184bdbc

Please sign in to comment.