This contacts manager application implements basic CRUD (Cread, Read, Update, and Delete) functionalities. A contact is an entity with a name, email, phone, and tags. The application allows you to list contacts based on their tag name, add new contacts, delete a contact, update a contact and search a contact based on a substring in the contact's name property.
I wanted to build this application in such a way that would allow me to reuse components, and make the maintainability of this app effortless.
I did a quick research and learn that most web applications have the the following components:
- Domain Logic
- Application Logic
- Presentation Layer
- State Management
- HTTP Library
- Other (Databases, ORM, Data Access, etc)
The domain logic (aka business logic) is the part of the program that actually solves the problem. It deals with how data can be created, updated, stored and more. For example, sending an email, calculating a salary, creating a new user.
The domain logic is concerned with the data itself.
The application logic is concerned with how the application works. For example: When the add contact button is clicked the application should present a modal window with a form. When an error occurs, the application should present an error message.
The application logic defines the applications's architecture and how it works.
The presentation layer is concerned with the application's UI, and binding events, and delegating that behavior to the domain logic.
The presentation layer responds to events triggered by user, browser, or 3rd party programs.
State Management helps in updating the UI in related places when there is a change in the application data due to action performed in the application like click, hover, etc. It also helps in making sure that state changes have been incorporated at corresponding places.
The 'state' allows UI components to stay in sync and should be considered the 'single source of truth' for component data and state component changes.
Some options include, the good ol' XMLHttpRequest object, The fetch API, and axios.
Allows you to make and receive HTTP requests
After falling down the rabbit hole of application architectures, I found 2 main common architectures:
- Model-View-Controller (MVC)
- The Flux Pattern
I did play around with the Flux pattern a bit using Redux, but it quickly got out of control. So, I thought MVC was the way to go. It is a lot simpler than the Flux pattern and makes separation of concerns much easier. I highly recommend this MVC article by Tania Rascia.
The Different Architectural concerns are divided as follows in the MVC pattern.
The layer the user interacts with
- UI Components
- Error messages
- Success Messages
- Binding Events
An intermediary between the Model and the View
- Application Logic
The layer that interacts with HTTP and dabase
- Domain Logic
- HTTP Library
- State Management
- As a user. I want to search for contacts, So that I can filter contacts by a substring in their name.
- As a user. I want to add a contact, So that I can save a contact I want.
- As a user. I want to update a contact, So that I can edit a contact with new info or fix incorrect info.
- As a user. I want to list a contact, So that I can view the contact in its own page.
- As a user. I want to delete a contact, So that I can remove unwanted or irrelevant contacts.
- As a user. I want to tag a contact, So that I can filter contacts based on that tag.
- As a user. I want to remove a tag, So that I delete a tag an unwanted tag from a contact.
- As a user. I want to favorite a contact, So that I can find my favorite contacts at a glance.
- As a user. I want to paginate contacts, So that I don't see all contacts at once.
- As a developer, I want to seed contact data, so that I can show paginated results.
- Create your own library to seed information using
faker.
- Create your own library to seed information using
User Story: As a user. I want to add a contact, So that I can save a contact I want.
- When the user clicks on a
Add Contactbuttom- Show a modal window with a form with the following fields:
Full Name(input field)Email(input field)Phone Number(input field)Tags(Multi-select options field)Custom Tag(input field)SubmitbuttonCancelbutton
- If the user clicks the
Submitbutton, then:- Add the contact information to the database.
- If the user clicks the
Cancelbutton, then:- Reset the form, and dismiss the modal.
- Show a modal window with a form with the following fields:
User Story: As a user. I want to update a contact, So that I can edit a contact with new info or fix incorrect info.
- When the user clicks on the
Editbutton- Show a modal window with a form with the following fields:
Full Namewith full name valueEmailwith email valuePhone Numberwith phone number valueTagsas multi-select options selectedCustom Tagwith empty input field valueSubmitbuttonCancelbutton
- If the user clicks
Submitbutton, then:- Save the updated user to the database
- If the user clicks
Cancelbutton, then:- Simply dismiss modal window, and do NOT persist changes.
- Show a modal window with a form with the following fields:
User Story: As a user. I want to delete a contact, So that I can remove unwanted or irrelevant contacts.
- When the user clicks on a
Deletebutton- Show a modal window with:
- Message:
Do you want to delete 'user name' from your contacts? CancelbuttonOKbutton
- Message:
- If user clicks on
Cancelbutton, then do nothing, and simply dismiss the modal window - If the user clicks on
OKbutton, then:- delete the user from the database
- update the view with new updated contacts list
- Show a modal window with:
User Story: As a user. I want to list a contact, So that I can view the contact in its own page.
- When the user clicks on contact's first name link
- Display a page about that contact
- Otherwise, display the list of contacts
User Story: As a user. I want to tag a contact, So that I can filter contacts based on that tag.
- When creating or updating a contact
- Be able to select an existing tag OR create a new tag
- Write user stories
- Write feature description
- Implement HTTP wrapper
/javascripts/modules/helpers/Http.js - Implement Model
/javascripts/modules/Model.jsHere I tried to decouple the
stateand tried to mimic the way an application is structured in the wild. - Implement all views and instantiate them in
/javascripts/modules/View.js - Export and Initialize Controller in
main.js
- Allow user to delete and edit tags.
- Allow user to create multiple tags at once.
- Show user the tags associated with them when contact form is loaded. (e.g. show checked checkboxes)
- Allow user to favorite contacts and render favorited contacts in dropdown in navbar.
- Store favorites in Local Storage.
- Add pagination
- Seed contacts function (add large amount of contacts)
- List a single user
