generated from bcgov/quickstart-openshift
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
a7fa68c
commit 184bdbc
Showing
136 changed files
with
1,755 additions
and
15,740 deletions.
There are no files selected for viewing
This file contains 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 |
---|---|---|
@@ -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 --> | ||
|
||
<!-- ``` --> |
This file contains 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.