Add a new page
Description
In this example we are going to add a new page to the project, and will go through each
individual steps for this process.
Here we are creating a page for Register Page. Which will have a form to list
contact details, form for address details and a submit button.
We will create the page itself first and add components.
Step 1: Create the index file for the page
- Go to
~/pagesfolder and create a new folder namedregister. - In this folder i.e,
~pages/registeradd a vue file nameindex.vue
Now we will make page to be accessible form <base-url>/register
Add the following code
<template>
<div class="content-container md:my-6">
<h3 class="header-text">
Create My Account <!--@todo: add this to translation -->
</h3>
<Panel>
<!-- Add components Here -->
</Panel>
</div>
</template>
<script>
import Vue from "vue";
import Panel from "~/components/UI/panel/Panel.vue";
export default Vue.extend({
name: "RegisterPage",
components: {Panel}
});
</script>
NOTES:
- All strings, texts, labels etc., will be rendered from the translation files
we will add these to all translations files upcoming steos. But uptill then it is a good habit to
mark them for
todo. - We have also imported the
Panelcomponent from~/components/UIfolder
Create Component files
This project heavily emphasises Single Responsibility Principle for it's component
so you should always keep in mind that if a page can be divided into multiple individual
components we should. And each component should idealy handle only one responsiblity.
Like in our case we will create two components for Contact details and for Address details.
Add ContactDetails Component
Create a component named ContactDetails.vue in ~/components/resister folder.
<template>
<div>
<h1 class="header-text-2">Contact Details</h1> <!--@todo: Add strings to translations -->
<form action="" method="post" class="mt-8 flex flex-col gap-6">
<div class="w-3/4 md:w-1/4">
<client-only>
<form-label class="gap-2">
<strong class="text-size-2 text-blue">Title*</strong> <!--@todo: Add strings to translations -->
<form-select
v-model="form.title"
:options="getTitleOptions()"
required
>
<template #first
><option disabled selected>Select Title</option> <!--@todo: Add strings to translations -->
</template>
</form-select>
</form-label>
</client-only>
</div>
<div class="w-1/2 md:w-1/2">
<form-label class="gap-2">
<strong class="text-size-2 text-blue"
>{{ $tc("register.labels.firstName") }}*</strong
>
<form-input v-model="form.firstName" type="text" required />
</form-label>
</div>
<div class="w-1/2 md:w-1/2">
<form-label class="gap-2">
<strong class="text-size-2 text-blue"
>{{ $tc("register.labels.lastName") }}*</strong
>
<form-input v-model="form.lastName" type="text" required />
</form-label>
</div>
<div class="w-1/2 md:w-1/2">
<form-label class="gap-2">
<strong class="text-size-2 text-blue">{{
$tc("register.labels.company")
}}</strong>
<form-input v-model="form.company" type="text" required />
</form-label>
</div>
<div class="w-1/2 md:w-1/2">
<form-label class="gap-2">
<strong class="text-size-2 text-blue"
>{{ $tc("register.labels.email") }}*</strong
>
<form-input v-model="form.email" type="text" required />
</form-label>
</div>
<div class="w-1/2 md:w-1/2">
<form-label class="gap-2">
<strong class="text-size-2 text-blue">{{
$tc("register.labels.landline")
}}</strong>
<form-input v-model="form.landline" type="text" required />
</form-label>
</div>
<div class="w-1/2 md:w-1/2">
<form-label class="gap-2">
<strong class="text-size-2 text-blue"
>{{ $tc("register.labels.mobile") }}*</strong
>
<form-input v-model="form.mobile" type="text" required />
</form-label>
</div>
</form>
</div>
</template>
<script lang="ts">
// ...
</script>
Import UI components
If there are components that alredy exists in the ~/components folder. We should use them.
Particularly the UI related components are already created in ~/components/UI folder.
Here we are importing FormLabel and FormInput components.
add the following in script tag.
import Vue from "vue";
import FormLabel from "~/components/UI/forms/FormLabel.vue";
import FormSelect from "~/components/UI/forms/FormSelect.vue";
import FormInput from "~/components/UI/forms/FormInput.vue";
export default Vue.extend({
name: "ContactDetails",
components: { FormInput, FormSelect, FormLabel },
data() {
return {
form: {
title: "",
firstName: "",
lastName: "",
landline: "",
mobile: "",
company: "",
email: "",
},
};
},
methods: {
getTitleOptions() {
// @todo: update options
return [
{
value: "Mr",
text: "Mr",
},
{
value: "Mrs",
text: "Mrs",
},
];
},
},
});
Add AddressDetails component
Add AddressDetails.vue file in ~/components/register/ folder.
<template>
<div>
<div class="w-1/2 md:w-1/2">
<form-label class="gap-2">
<strong class="text-size-2 text-blue"
>{{ $tc("register.labels.address") }}*</strong
>
<form-input v-model="address" type="text" required />
</form-label>
</div>
<p class="text-size-4 font-bold text-blue">
{{ $tc("register.addressDetailsNote") }}
</p>
</div>
</template>
<script lang="ts">
//...
</script>
####Add the following in script tag
import Vue from "vue";
import FormLabel from "~/components/UI/forms/FormLabel.vue";
import FormInput from "~/components/UI/forms/FormInput.vue";
export default Vue.extend({
name: "AddressDetails",
components: { FormInput, FormLabel },
data() {
return {
address: "",
};
},
});
Step 3: Add the components to the main page
In ~/pages/resgister/index.vue add the above made components and also include DefaultButton component
from the UI folder for submit button.
<template>
<div class="content-container md:my-6">
<h3 class="header-text">
{{ $tc("login.createAccount") }}
</h3>
<Panel>
<ContactDetails />
<HorizontalSeparator />
<AddressDetails />
<HorizontalSeparator />
<DefaultButton @clickAction="register"> Continue </DefaultButton>
</Panel>
</div>
</template>
<script lang="ts">
import Vue from "vue";
import Panel from "~/components/UI/panel/Panel.vue";
import ContactDetails from "~/components/register/ContactDetails.vue";
import DefaultButton from "~/components/UI/button/DefaultButton.vue";
import HorizontalSeparator from "~/components/UI/separators/HorizontalSeparator.vue";
import AddressDetails from "~/components/register/AddressDetails.vue";
export default Vue.extend({
name: "RegisterPage",
components: {
AddressDetails,
HorizontalSeparator,
DefaultButton,
ContactDetails,
Panel,
},
data() {
return {};
},
methods: {
register(event: any) {
//... @todo: write code here
},
},
});
</script>
Step 4: Update UI using Tailwind.css
Now that we have the basic structure you can update the UI using tailwind classes to make it match the exact design given by the client.
Step 5: Add translation files
Now that we have the basic UI and interface setup we can add the strings used to the translation files
- Go to
~/utils/translations/data/UK-EN.jsonfile - Include the following properties at the end.
"register": { "createAccount": "Create my account", "contactDetails": "Contact Details", "labels": { "title": "Title", "firstName": "First Name", "lastName": "Last Name", "landline": "Landline", "mobile": "Mobile", "company": "Company", "email": "E-mail", "address": "Your Address", "password": "Password", "confirmPassword": "Confirm Passoword" }, "placeholder": { "title": "Select" }, } - In the
vuefiles for components and page replace the stings with appropriate strings For example, to update the header text in the pageSimilarly, for updating labels in component files use<h3 class="header-text"> {{ $tc("register.createAccount") }} </h3><strong class="text-size-2 text-blue"> {{ $tc("register.labels.firstName") }}* </strong> - Important: Update all other translation files for all other regions specifed in
~/utils/translations/data/folder. In case you do not know translation for any specific region, you can paste the same translation as that inUK-en.json.
Step 6: Add API layer
- Take reference for
Toolstation API Documenttionhere. If you don't have access please check Team's Project Credentials page or contact your reporting manager. - Add
account.api.tsfile in~services/apifolder.
import { NuxtAxiosInstance } from "@nuxtjs/axios";
import { AxiosResponse } from "axios";
const ENDPOINTS = {
ACCOUNT: (accountId: string) => `/accounts/${accountId}`,
ACCOUNT_CUSTOMERS: (accountId: string) => `/accounts/${accountId}/customers`,
ACCOUNT_CUSTOMER: (accountId: string, customerId: string) =>
`/accounts/${accountId}/customers/${customerId}`,
ACCOUNT_ORDERS: (accountId: string) => `/accounts/${accountId}/orders`,
};
export const getAccount = async (
$axios: NuxtAxiosInstance,
accountId: string
): Promise<AxiosResponse<any>> =>
await $axios.$get(ENDPOINTS.ACCOUNT(accountId));
export const getAccountCustomers = async (
$axios: NuxtAxiosInstance,
accountId: string
): Promise<AxiosResponse<any>> =>
await $axios.$get(ENDPOINTS.ACCOUNT_CUSTOMERS(accountId));
export const createAccountCustomer = async (
$axios: NuxtAxiosInstance,
accountId: string,
data: any
): Promise<AxiosResponse<any>> =>
await $axios.$post(ENDPOINTS.ACCOUNT_CUSTOMERS(accountId), data);
export const deleteAccountCustomer = async (
$axios: NuxtAxiosInstance,
accountId: string,
customerId: string
): Promise<AxiosResponse<any>> =>
await $axios.$delete(ENDPOINTS.ACCOUNT_CUSTOMER(accountId, customerId));
Step 7: Add Service layer
Add the account.services.ts in ~/services folder.
// TODO