I.D.E. - WebStorm
Install Node.js and execute npm install --global yarn
To install dependecies: yarn install
To start the front-end server: yarn start
The current system is intended to be a lightweight web app, thus it has been built in the form of a Single Page Application (SPA).
The user interface has no back-end API to the Energy Management System (EMS), therefore dummy data has been used for generating the graph on the Schedule page.
The user needs to connect to the system using a QR code.
This section provides an overview of the entire system and its functionalities. The section covers frameworks and tools used during the development of the web application, as well as describes styling, reporository structres and provides throughout description of the main components.
Below is the Table of all frameworks and tools used during the product implementation.
Framework/Library | Usage |
---|---|
React | Functional components to build UI |
Typescript | Static typing for Javascript |
React Hook Form | Hook for functional components to handle the state of the form |
Reactstrap | React Bootstrap 4 library |
Material UI | React Component Library |
Typedoc | Documentation generator |
Firebase | Deployment of the UI |
Cypress | Unit & System Testing |
The next paraghraphs provide overview of styling techniques used in the project, as well as describe how responsiveness of the pages was achieved.
The styles folder contains scss files for each of the main component (and styles for all child components), as well global styling variables for light mode (lightMode.scss) and dark mode (darkMode.scss). Currently the application operates on light mode only.
The individual scss files for the main pages (Start, Schedule, Session and Feedback) are constructed using nested classes. This specifies the class name of the elements precisely and ensures that they would not be overwritten by accident. In the example below the .feedbackForm element is wrapped inside the .feedback parent element:
example from feedback.scss file
.feedback {
display: flex;
align-items: center;
background: $global_background_color;
flex-direction: column;
...
.feedbackForm {
display: flex;
align-items: center;
flex-direction: column;
height: 100%;
justify-content: center;
}
...
}
To achieve smooth behaviour of the Time Selector, its style was defined separetly in timeSelector.scss.
Inline styling was used in cases when the element needed minor touching, but not be overwritten completely. For example to increase/decrease margin
/ padding
or align texts in the center.
The web appication resizes to a smartphone screen. This was achieved using Flexbox properties in the CSS. Most of the components are defined using Container, Row, Column
components from reactstrap
. Please consider the example below:
<Container>
<Row>
<Column>
... content
</Column>
</Row>
</Container>
The App.scss and index.scss files overwrite styling of html and body to allow content spread at full screen. Most of the Container
's also use display: flex
property to align and justify the content.
Please refer below for the detailed overview of the Repository structure.
.
├── cypress # Compiled files
| ├── ...
| └── integration # Cypress testing files for each main component
|
├── docs # Typedoc documentation files
├── public # Public files (e.g. car image)
├── src # Source folder
| ├── api # Mock api file
| ├── assets # Profile Steering files
| ├── components # React components
| | ├── pages # Main React pages/components
| | ├── styled # Styled MUI/Reactstrap components
| | └── widgets # Complex styled components used on the main pages
| ├── data # Dummy data
| ├── hooks # Hook for the mock API
| ├── styles # SCSS files
| ├── index.tsx # Entry point of the web application
| └── ...
├── test # Manual testing
├── firebase.json # Firebase config file
|── package.json # Project's metadata
├── package-lock.json # NPM files dependency tree (DO NOT EDIT DIRECTLY)
|── tsconfig.json # Typescript config file
|── cypress.json # Cypress config file
|── README.md # Manual file
└── ...
This is the initial page when the web app is started and it only allows users to proceed to the next page.
This page is used for the scheduling of the charging session. The user can enter their preferences and see the planned session together with the price and CO2 emissions. If the user requests 0 kWh of energy or does not select a charging mode, the UI should reject the session and ask the user to set the energy and/or mode.
This component keeps track of the charging session. The state of charging is updated through a progress bar and a table. This page supports three phases, with the following distinctions:
The “Stop” button triggers the pop-up which asks for a confirmation of the abortion. The pop-up comes with two button options: “Yes” and “Cancel”. In case the user choose “Yes”, the session page will be in the abortion phase described above. If “Cancel” is picked, the session will still be in progress, remaining in the same phase.
The “Finish” button will redirect the user to the Feedback page.
The table shows the expected finish time of charging at the top, followed by the progress state of the requested energy from the user, taken from the Schedule page, in the form of both kWh and km charged. The charging mode, price, and CO2 emissions of the charging session are also displayed in the table.
The Feedback component stores the feedback from users after each charging session. React-Hook-Form manages the state of the form. The form is unitialised using useForm()
hook, which takes defaultValues
(of the input fields) and (validation) mode
as parameters. The form is wrapped in FormProvider
which passes the form
object and its context to child components.
Users may either submit feedback or exit the feedback session. In case the feedback is submitted the alert message "Thank you for your feedback!"
appears on top of the screen and the user is redirected back to the Start page after timeout. In case no feedback is submitted, the alert displays "Please rate us next time! Your feedback is very important for us :)"
and the user is redirected to Start page after timeout. The state of the alert is set in useEffect()
.
The boolean hasFeedback
determines if any feedback was submitted. If the form is dirty (if any of the fields are not the same as default values anymore) and if user did not touch any of the fields, then the hasFeedback
is set to true
.
The form consists of 3 fields (Controlled Components):
Each field is wrapped in Controller with control of the form passed as context.control
via useFormContext()
.
None of the fields of the Feedback Form are mandatory. The Suggested Comments component dynamically generates Radioboxes depending on the number of elemnets in the values
prop inherited from Feedback. So in order to change number of suggested comments or their values, the only modification that needs to be made is add/change/remove elements of commmentValues
array in the Feedback page.
If in future it will be decided to allow users to choose one or more suggested comments, radiobox need to be substituted with checkboxes. For that Checkbox styled component was defined (which is currently unused).
The styling of Feedback page and its child components is defined in feedback.scss file.
System testing is done in Cypress and all the test files can be found in this directory
── cypress # Compiled files
| ├── ...
| └── integration # Cypress testing files for each main component
Hosting is done using Firebase. In order to preview execute yarn build
and firebase hosting:channel:deploy branch-preview-name
and to release in production use firebase deploy --only hosting
. For more information please refer to the Firebase documentation.
To add a new component for a new feature, make a .tsx file in the widgets package and export a function that returns the type of the widget you make.
Within this function, you can return an HTML literal with the markup of the widget.
Hooks and values for this widget can be initialized in this function, whereas the model (the blueprint for the properties of the component) can be defined as an interface above.
This procedure is similar for the styled components.
To insert a widget into a page, you can start using the widget with an HTML tag.
To add a new page to the application, add a <Route>
tag with the corresponding URI template to App.tsx
.
To modify the content of widgets, you can go to the page and access the content of the component there.
In case the same data structure is used in multiple modules, it is better to centralize a definition of this data structure in the models package.
The recommended way to implement API calls is within custom hooks, similar to useProgress
.
The connection to the API itself can be defined in the api package, which also allows for multiple APIs to work with the UI.
You can write a .scss file (stylesheet) to house styling rules. The stylesheets can inherit properties from each other, which means that you do not have to duplicate style values but instead can set them as variables to call back elsewhere.
The code was documented using TypeDoc and can be found in here.
To generate new documentation simply execute yarn docs
.
Generated using TypeDoc