# Page internal routing * The SPA is loaded from the BACKOFFICE_URL * The view to be rendered is decided by the URL fragment * Query parameters that may affect routing - instance: use from the default instance to mimic another instance management * The user must provide BACKEND_URL or BACKOFFICE_URL will use as default * Token for querying the backend will be saved in localStorage under backend-token-${name} # HTTP queries to the backend HTTP queries will have 4 states: * loading: request did not end yet. data and error are undefined * ok: data has information, http response status == 200 * clientError: http response status is between 400 and 499 - notfound: http status 404 - unauthorized: http status 401 * serverError: http response status is grater than 500 There are categories of queries: * sync: getting information for the page rendering * async: performing an CRUD operation ## Loading the page information (sync) In this scenario, a failed request will make the app flow to break. When receiving an not found error a generic not found page will be shown. If the BACKEND_URL points to a default instance it should send the user to create the instance. When receiving an unauthorized error, the user should be prompted with a login form. When receiving an another error (400 < http status < 600), the login form should be shown with an error message using the hint from the backend. On other unexpected error (like network error), the login form should be shown with an error message. ## CRUD operation (async) In this scenario, a failed request does not break the flow but a message will be prompted. # Forms All the input components should be placed in the folder `src/components/from`. The core concepts are: * /> places instead of
it should be mapped to an object of type T * an others: defines UI, create DOM controls and access the form with useField() To use it you will need a state somewhere with the object holding all the form information. ``` const [state, setState] = useState({ name: '', age: 11 }) ``` Optionally an error object an be built with the error messages ``` const errors = { field1: undefined, field2: 'should be greater than 18', } ``` These 3 elements are used to setup the FormProvider ``` ...inputs ``` Inputs should handle UI rendering and use `useField(name)` to get: * error: the field has been modified and the value is not correct * required: the field need to be corrected * value: the current value of the object * initial: original value before change * onChange: function to update the current field Also, every input must be ready to receive these properties * name: property of the form object being manipulated * label: how the name of the property will be shown in the UI * placeholder: optional, inplace text when there is no value yet * readonly: default to false, will prevent change the value * help: optional, example text below the input text to help the user * tooltip: optional, will add a (i) with a popup to describe the field # Custom Hooks All the general purpose hooks should be placed in folder `src/hooks` and tests under `tests/hooks`. Starts with the `use` word. # Contexts All the contexts should be placed in the folder `src/context` as a function. Should expose provider as a component `` and consumer as a hook function `useXxxContext()` (where XXX is the name) # Components Type of components: * main entry point: src/index.tsx, mostly initialization * routing: in the `src` folder, deciding who is going to take the work. That's when the page is loading but also create navigation handlers * pages: in the `paths` folder, setup page information (like querying the backend for the list of things), handlers for CRUD events, delegated routing to parent and UI to children. Some other guidelines: * Hooks over classes are preferred * Components that are ready to be reused on any place should be in `src/components` folder * Since one of the build targets is a single bundle with all the pages, we are avoiding route based code splitting https://github.com/preactjs/preact-cli#route-based-code-splitting # Testing Every components should have examples using storybook (xxx.stories.tsx). There is an automated test that check that every example can be rendered so we make sure that we do not add a regression. Every hook should have examples under `tests/hooks` with common usage trying to follow this structure: * (Given) set some context of the initial condition * (When) some action to be tested. May be the initialization of a hook or an action associated with it * (Then) a particular set of observable consequences should be expected # Accessibility Pages and components should be built with accessibility in mind. https://github.com/nickcolley/jest-axe https://orkhanhuseyn.medium.com/accessibility-testing-in-react-with-jest-axe-e08c2a3f3289 http://accesibilidadweb.dlsi.ua.es/?menu=jaws https://webaim.org/projects/screenreadersurvey8/#intro https://www.gov.uk/service-manual/technology/testing-with-assistive-technologies#how-to-test https://es.reactjs.org/docs/accessibility.html # Internationalization Every non translated message should be written in English and wrapped into: * i18n function from useTranslator() hook * component Makefile has a i18n that will parse source files and update the po template. When *.po are updated, running the i18n target will create the strings.ts that the application will use in runtime. # Documentation Conventions * labels * begin w/ a capital letter * acronyms (e.g., "URL") are upper case * tooltips * begin w/ a lower case letter * do not end w/ punctuation (period) * avoid leading article ("a", "an", "the")