For my midterm, I created an address book app meant to be used as an internal communications tool for a company. Many large companies have several different departments, such as an HR department, Accounting department, etc. Companies with multiple products will also have separate interdisciplinary teams for each product. I designed my address book with the need to communicate with and across teams in mind.
Recontextualizing the assignment to fit my vision, I added the department that a contact works in to the information displayed on a contact card. I also changed address to be the location of the company’s branch offices. When sorting the list, in addition to first and last name, the user can also sort by department and branch location. The contact list can also be filtered by the department.
Additionally, my address book includes a list of teams to the right of the list of contacts. Using the list of teams allows the user to send a group message to everyone in the team. The user may also use the team list to find the contact card of a single member of the team.
Some use cases that I can imagine for my app include some of the following:
- The leader of a team wants to message everyone about a meeting
- A higher up needs to find the leader of a certain project
- A team completes a prototype and wants to send it off to QA for testing
- A programmer on one project heard that the programmer on another team implemented a similar function and wants to seek advice from them.
The app’s main component is the Contact component. This component receives a first and last name, department, address, and image as props. Each Contact also features a message button. The callback function associated with this button causes the app to render the Messagebox component and takes the Contact’s name as an argument.
The Messagebox component consists of 3 input fields. The “To” and “Subject” areas are both normal text inputs, while the email body is a text area. The message recipient is fixed based on the contact that triggered OpenMessageBox function and cannot be changed. The Messagebox component has its own state with separate fields for the subject and the body. These values are set with an onChange function attached to the input fields. The Cancel and Send buttons both call the same onClick function, which resets the state of the subject and body back to an empty string. The onClick also calls the callback function that tells the parent App which button was clicked, and plays a CSS animation of a “message sent” notification if it was the Send button.
The Search component works similarly to previous input components that we have built in that it contains its own state as an intermediary to the value that gets rendered in the actual field. Upon updating, the Search component tells the app what’s inside of it, and sets the parent app’s Search state to that same value. The search is applied in the parent’s render function and searches first and last name. The search is not case sensitive. Originally, I also allowed for searching by department. However, this filtered out a lot fewer contacts when typing in the first few letters, making it more difficult to actually find the contact you want by searching. Additionally, that functionality overlapped with the Filter component, so I eventually decided that it was best to remove searching by department.
The final component is the Team component. This component is very similar to the Contact component and shares much of the same CSS. However, its props vary slightly. Rather than a first and last name, it only receives a single team name. The Team component also receives a list of the team members and their position titles. Like the Contact component, the Team component can also open a Messagebox, setting all of the team members as the recipients. Notably, each team member’s name can be clicked, which will isolate their contact card in the list of contacts on the left side.
- CSS. CSS and general aesthetic design are two of my biggest weaknesses
- Figuring out how to structure the messaging functionality. Although the Messagebox is its own component, in the beginning I was unsure what it should be a child of. Because the Contact component is the one that contains the button that triggers the Messagebox opening, I thought that it should belong to that component. However, there are several Contact components and I only wanted one Messagebox. After considering, “what’s a React way of doing things?”, I concluded that the main app should track whether the Messagebox should be open or closed in the state. When the Messagebox field in state determines that the Messagebox component should not render, it adds the “Off” class to the component. This class’ style is set to display: none. The callback function associated with the Message buttons, openMessageBox, removes this class.
- Allowing for clicking a specific member of a team. Originally, I wanted the teamMembers prop to contain references to the actual Contact component of all of the members, but I had no idea how to do this with dynamic components. First, I tried to give every contact a unique id prop, pass the id as a props to the Team component in lieu of a name, and then somehow derive the correct information from the state’s contactList. This was insanely complicated, and I could not figure out how to make it work. I later realized that my goal was essentially just filtering, which my searching function already does, so I added another callback function that calls the same function that sets the search term in the parent app. In addition to showing only the clicked name in the list of Contacts, the name also appears in the Search bar. This has the added benefit of being able to return to the default state of the app by simply clearing the Search bar.
- My friends Jamie and Kate for giving feedback on the color palette, side margins, and general layout.
- Black Panther’s imdb page, which I downloaded all of the images from.