GithubHelp home page GithubHelp logo

amex-demo-server's Introduction

Project: Create an "Order Tracking" application

Application purpose

To amplify the productivity of customer service representatives (CSR). You will create an application that allows CSRs to create and modify both customers and their orders, search a product catalog against which orders can be created, and manage the functional lifecycle of all orders.

Tech stack

  • Backend (API):
    • Express/Node.js
    • Sequelize
  • Frontend:
    • React with axios
    • Wireframing: Figma is recommended
  • Backend (Database):
    • MySQL
  • CI/CD:
    • Github actions will be used for CI/CD pipelines
  • Deployment: Heroku for both front-end and API

Overall System Architecture

Overall System Architecture

Order lifecycle

  • Customer calls in an order
  • CSR adds Customer if not existing
  • CSR edits Customer as needed
  • CSR creates an Order
  • Add Product(s)
    • Check if available
    • Add if so
  • CSR informs shipping to assemble and ship the Order
  • Shipping collects Products in Order
  • Conditional at any point prior to shipping: Customer calls in to modify existing Order
  • Order is shipped
  • Order arrives
  • Shipping agent informs CSR
  • Order is closed

Business constraints (Understand how these affect the Order lifecycle)

  • Can't add a Product if none available
  • Can't modify an Order that has been shipped
  • Can't close out an Order without confirmation that Order arrived as expected

Business objects

  • Customers
    • id (PK)
    • first_name
    • middle_name
    • last_name
    • phone
    • email
    • customer_notes
    • address_id (FK)
  • Orders
    • id (PK)
    • customer_id (FK)
    • order_status (Draft/Open/Finalized/Preparing to ship/Ready for shipping/Shipped/Delivered/Closed)
    • datetime_order_placed
    • total_order_price
    • order_notes
  • Products
    • id (PK)
    • product_SKU
    • product_price
    • product_name
    • product_quantity
    • product_description
  • Addresses
    • id (PK)
    • address_line_1
    • address_line_2
    • city
    • state
    • zip

The above listing of data fields is not necessarily comprehensive. You'll also observe that a real database schema is only hinted at. This is not a prescriptive data model, and it's a fact of software development that data models change over time; that's why there is an entire art of schema migrations. One thing clearly lacking from the above is a means by which to link together the customers, orders, and products.

Application requirements

CSRs need to be able to

  • Perform CRUD operations for Orders, including the ability to interactively add products from the Product catalog to an order that is in progress
  • There must be the ability to save an Order as a draft
  • Tie the order to a Customer
  • Browse the product catalog (as a CSR adds or removes products from an order, the product count needs to be updated)
  • Browse the customer database
  • Track and change the shipping status of the order

API starting point

Method URLs Actions
GET api/customers Get all customers
GET api/customers/:id Get specific customer
POST api/customers Create new customer
PUT api/customers/:id Modify existing customer
DELETE api/customers/:id Remove customer (data compliance/right to be forgotten)
GET api/orders Get all orders
GET api/orders/:id Get specific order
POST api/orders Create new order (think about how to differentiate between draft and live orders)
PUT api/orders/:id Modify existing order
DELETE api/orders/:id Delete a draft order (shouldn't allow for deletion of live orders)
GET api/products Get all products
GET api/products/:id Get specific product
PUT api/products/:id Increment/Decrement product inventory

Notes

Faking data for the dB: http://marak.github.io/faker.js/ Data types for Sequelize: https://sequelize.org/v5/manual/data-types.html Manual for Sequelize migrations: https://sequelize.org/v3/docs/migrations/ Great example of migrations in Express app: https://developers.decoded.africa/index.php/2020/07/30/how-to-setup-a-node-express-js-project-with-sequelize-cli/

amex-demo-server's People

Watchers

Erik Gross avatar Hou Chia avatar moekoko avatar  avatar  avatar

amex-demo-server's Issues

User-story-17: List all products

User-story-17: List all products

As a CSR, I would like to view a list of all products, so that I know what’s available in the inventory

Acceptance Criteria:

Given that I am on the Products page,
Whenever the page is loaded,
Then I see a list of products (ordered alphabetically by the product name).

Requirements/Validations:

Frontend

  • Navigating to the /products path should - route the user to the Products page, which displays a list of all available products and increment/decrement buttons for each product for inventory update purposes
  • Display each product’s SKU, price, name, and quantity.

Backend

  • The API GET api/products should return a status code of 200 and a set of all orders record(s) as JSON (see "Outputs" section below).

Inputs:

  • None

Outputs:

The API GET api/products will return a status code of 200 and a set of all orders record(s) as JSON:

[{
  "id": 1,
  "SKU": "EDMoh9v0",
  "price": 83,
  "name": "ultrices posuere cubilia curae mauris viverra diam vitae quam suspendisse potenti nullam porttitor lacus at",
  "quantity": 65,
  "description": "Fusce lacus purus, aliquet at, feugiat non, pretium quis, lectus. Suspendisse potenti. In eleifend quam a odio. In hac habitasse platea dictumst. Maecenas ut massa quis augue luctus tincidunt."
}, {
  "id": 2,
  "SKU": "nJhBQD",
  "price": 83,
  "name": "in felis donec semper sapien a libero nam dui proin leo odio porttitor id consequat in consequat",
  "quantity": 91,
  "description": "Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec pharetra, magna vestibulum aliquet ultrices, erat tortor sollicitudin mi, sit amet lobortis sapien sapien non mi. Integer ac neque. Duis bibendum. Morbi non quam nec dui luctus rutrum. Nulla tellus. In sagittis dui vel nisl. Duis ac nibh. Fusce lacus purus, aliquet at, feugiat non, pretium quis, lectus. Suspendisse potenti."
}, {
  "id": 3,
  "SKU": "fF68tULm5",
  "price": 64,
  "name": "aliquam convallis nunc proin at turpis a pede posuere nonummy integer non velit donec diam neque",
  "quantity": 65,
  "description": "Nam congue, risus semper porta volutpat, quam pede lobortis ligula, sit amet eleifend pede libero quis orci. Nullam molestie nibh in lectus. Pellentesque at nulla. Suspendisse potenti."
}, {
  "id": 4,
  "SKU": "cDclcX5",
  "price": 46,
  "name": "pretium quis lectus suspendisse potenti in eleifend quam a odio in hac habitasse platea dictumst maecenas ut massa quis augue",
  "quantity": 19,
  "description": "Nulla tellus. In sagittis dui vel nisl. Duis ac nibh."
}, {
  "id": 5,
  "SKU": "9qmKkKw",
  "price": 26,
  "name": "a nibh in quis justo maecenas rhoncus aliquam lacus morbi quis tortor id nulla ultrices aliquet",
  "quantity": 90,
  "description": "Donec ut dolor. Morbi vel lectus in quam fringilla rhoncus. Mauris enim leo, rhoncus sed, vestibulum sit amet, cursus id, turpis. Integer aliquet, massa id lobortis convallis, tortor risus dapibus augue, vel accumsan tellus nisi eu orci. Mauris lacinia sapien quis libero."
}]

Recommended steps

  1. Create a simple wireframe (styles NOT needed) for the page.
  2. Determine what components are needed for the page
  3. Create the folder/files for the components, and create static components in each file.
  4. Set up the routes needed to route the user to the placeholder components
  5. Add state/props and other functionality to your components.
  6. Since your backend is not likely built yet while you're creating the front-end, you can add test data to db.json and use the fake json-server API instead.
  7. Build out the backend.
  8. Update the front-end to call the real backend API. Make sure everything works.
  9. When everything is working, style your application. Follow the style guide
  10. Refactor your code, as needed.

Resources

User-story-7: Retrieve a specific customer’s record

User-story-7: Retrieve a specific customer’s record

As a CSR, I would like to view a specific customer’s records, so that I can gather vital business information about the customer.

Acceptance Criteria:

Given that I am on the Customers page,
When I click on a customer in the list of customers,
Then I am redirected to the Customer Detail page that displays the customer’s information.

Requirements/Validations:

Frontend

  • Navigating to /customers/:id should route the user to the Customer Detail page which displays an individual customer’s personal information, along with the customer’s address and order history
  • Clicking on each Order in the Order History will route the user to the Order Detail page.

Backend

  • The API GET api/customers/:id will return a status code of 200 and the specific customer record as JSON (see the "Outputs" section below).

Inputs:

None

Outputs:

The API GET api/customers/:id will return a status code of 200 and the specific customer record as JSON:

{
  "id": 1,
  "first_name": "Bernadine",
  "middle_name": "Ulysses",
  "last_name": "Ownsworth",
  "phone": "516-768-8190",
  "email": "[email protected]",
  "notes": "Curabitur convallis.",
  "address_id": 10
}

Recommended steps

  1. Create a simple wireframe (styles NOT needed) for the page.
  2. Determine what components are needed for the page
  3. Create the folder/files for the components, and create static components in each file.
  4. Set up the routes needed to route the user to the placeholder components
  5. Add state/props and other functionality to your components.
  6. Since your backend is not likely built yet while you're creating the front-end, you can add test data to db.json and use the fake json-server API instead.
  7. Build out the backend.
  8. Update the front-end to call the real backend API. Make sure everything works.
  9. When everything is working, style your application. Follow the style guide
  10. Refactor your code, as needed.

Resources

User-story-10 Search a customer by email

User-story-10 Search a customer by email

As a CSR, I would like to search for a customer by email, so that I can quickly access a customer's information when they contact me about their order.

Acceptance Criteria:

Given that I am on the Customers page,
When I submit a partial or complete email using the search bar,
Then I see a list of customer records on the page if the customer(s) exist, or an error message if no customer is found.

Requirements/Validations:

Frontend:

  • Navigating to the /customers path should route the user to the Customers page which displays a search bar

Backend:

  • The API GET api/customers should return a status code of 200 and a set of customer record(s) that meet the search query as JSON (see the "Outputs" section below).

Inputs:

  • Partial or complete email

Outputs:

The API GET api/customers will return a status code of 200 and a set of customer record(s) that meet the search query as JSON:

[{
  "id": 1,
  "first_name": "Bernadine",
  "middle_name": "Ulysses",
  "last_name": "Ownsworth",
  "phone": "516-768-1443",
  "email": "[email protected]",
  "notes": "Curabitur convallis."
}, {
  "id": 2,
  "first_name": "Ruddie",
  "middle_name": "Merwyn",
  "last_name": "Bussell",
  "phone": "117-873-1443",
  "email": "[email protected]",
  "notes": "Mauris ullamcorper purus sit amet nulla."
}, {
  "id": 3,
  "first_name": "Reade",
  "middle_name": "Byran",
  "last_name": "Figgen",
  "phone": "379-317-1443",
  "email": "[email protected]",
  "notes": "Sed vel enim sit amet nunc viverra dapibus. Nulla suscipit ligula in lacus."
}]

Recommended steps

  1. Create a simple wireframe (styles NOT needed) for the page.
  2. Determine what components are needed for the page
  3. Create the folder/files for the components, and create static components in each file.
  4. Set up the routes needed to route the user to the placeholder components
  5. Add state/props and other functionality to your components.
  6. Since your backend is not likely built yet while you're creating the front-end, you can add test data to db.json and use the fake json-server API instead.
  7. Build out the backend.
  8. Update the front-end to call the real backend API. Make sure everything works.
  9. When everything is working, style your application. Follow the style guide
  10. Refactor your code, as needed.

Resources

User-story-9: Delete a customer

User-story-9: Delete a customer

As a CSR, I would like to delete a customer from the system, so that the system is kept up-to-date with active customers only and so the system can be compliant with right-to-be-forgotten rules

Acceptance Criteria:

Given that I am on the Customer Detail page,
And I see the list of existing customers/customer,
When I press the delete button next to a customer’s record,
Then the customer’s record is deleted from the system and it no longer appears on the Customers page.

Requirements/Validations:

Frontend

  • On the Customer Detail page at the /customers/:id path, there should be a Delete button next to each customer's record.
  • When the Delete button is pressed, display a confirmation modal asking the CSR to confirm that they indeed would like to delete the customer. Clicking "Cancel" makes no changes, whereas clicking “Confirm” deletes the customer record and refreshes the list of customers on the page.

Backend

  • If the operation is successful, the API endpoint DELETE api/customers/:id will return a status code of 204 (see the "Outputs" section below).

Inputs:

None

Outputs:

If the operation is successful, the API endpoint DELETE api/customers/:id will return a status code of 204.

Recommended steps

  1. Create a simple wireframe (styles NOT needed) for the page.
  2. Determine what components are needed for the page
  3. Create the folder/files for the components, and create static components in each file.
  4. Set up the routes needed to route the user to the placeholder components
  5. Add state/props and other functionality to your components.
  6. Since your backend is not likely built yet while you're creating the front-end, you can add test data to db.json and use the fake json-server API instead.
  7. Build out the backend.
  8. Update the front-end to call the real backend API. Make sure everything works.
  9. When everything is working, style your application. Follow the style guide
  10. Refactor your code, as needed.

Resources

User-story-5: List all customers

User-story-5: List all customers

As a CSR, I would like to view a list of the most recently added customers, so that I can follow up with them regarding their orders.

Acceptance Criteria:

Given that I am on the Customers page,
Whenever the page is loaded,
Then I see a list of the customers (ordered from most to least recently added).

Requirements/Validations:

Frontend

  • Navigating to the /customers or / path should route to the Customers page which displays a list of customers. This route is the home page/dashboard for the application
  • The page should display each customer’s id, first name, last name, phone, city and zipcode

Backend

  • The API GET api/customers will return a status code of 200 and a set of all customer record(s) as JSON (see the "Outputs" section below).

Inputs:

None

Outputs:

The API GET api/customers will return a status code of 200 and a set of all customer record(s) as JSON:

[{
  "id": 1,
  "first_name": "Bernadine",
  "middle_name": "Ulysses",
  "last_name": "Ownsworth",
  "phone": "516-768-8190",
  "email": "[email protected]",
  "notes": "Curabitur convallis.",
  "address_id": 1
}, {
  "id": 2,
  "first_name": "Ruddie",
  "middle_name": "Merwyn",
  "last_name": "Bussell",
  "phone": "117-873-1443",
  "email": "[email protected]",
  "notes": "Mauris ullamcorper purus sit amet nulla.",
  "address_id": 2
}, {
  "id": 3,
  "first_name": "Reade",
  "middle_name": "Byran",
  "last_name": "Figgen",
  "phone": "379-317-2206",
  "email": "[email protected]",
  "notes": "Sed vel enim sit amet nunc viverra dapibus. Nulla suscipit ligula in lacus.",
  "address_id": 3
}, {
  "id": 4,
  "first_name": "Hernando",
  "middle_name": "Janet",
  "last_name": "Catley",
  "phone": "621-883-6154",
  "email": "[email protected]",
  "notes": "Suspendisse potenti.",
  "address_id": 4
}, {
  "id": 5,
  "first_name": "Grata",
  "middle_name": "Benito",
  "last_name": "Atling",
  "phone": "705-418-3300",
  "email": "[email protected]",
  "notes": "Aliquam augue quam, sollicitudin vitae, consectetuer eget, rutrum at, lorem.",
  "address_id": 5
}, {
  "id": 6,
  "first_name": "Laina",
  "middle_name": "Hugh",
  "last_name": "Colbridge",
  "phone": "130-840-0484",
  "email": "[email protected]",
  "notes": "Phasellus sit amet erat.",
  "address_id": 6
}, {
  "id": 7,
  "first_name": "Elysee",
  "middle_name": "Raleigh",
  "last_name": "Hagart",
  "phone": "674-806-7510",
  "email": "[email protected]",
  "notes": "Integer pede justo, lacinia eget, tincidunt eget, tempus vel, pede.",
  "address_id": 7
}, {
  "id": 8,
  "first_name": "Burtie",
  "middle_name": "Lloyd",
  "last_name": "Sawdon",
  "phone": "382-341-5595",
  "email": "[email protected]",
  "notes": "Donec vitae nisi. Nam ultrices, libero non mattis pulvinar, nulla pede ullamcorper augue, a suscipit nulla elit ac nulla.",
  "address_id": 8
}, {
  "id": 9,
  "first_name": "Levy",
  "middle_name": "Eugenio",
  "last_name": "Rief",
  "phone": "861-169-9885",
  "email": "[email protected]",
  "notes": "Proin interdum mauris non ligula pellentesque ultrices.",
  "address_id": 9
}, {
  "id": 10,
  "first_name": "Leigha",
  "middle_name": "Mathilda",
  "last_name": "Auguste",
  "phone": "666-249-7625",
  "email": "[email protected]",
  "notes": "Aenean auctor gravida sem. Praesent id massa id nisl venenatis lacinia.",
  "address_id": 10
}]

Recommended steps

  1. Create a simple wireframe (styles NOT needed) for the page.
  2. Determine what components are needed for the page
  3. Create the folder/files for the components, and create static components in each file.
  4. Set up the routes needed to route the user to the placeholder components
  5. Add state/props and other functionality to your components.
  6. Since your backend is not likely built yet while you're creating the front-end, you can add test data to db.json and use the fake json-server API instead.
  7. Build out the backend.
  8. Update the front-end to call the real backend API. Make sure everything works.
  9. When everything is working, style your application. Follow the style guide
  10. Refactor your code, as needed.

Resources

Setup the client repo on Github

  • This should be created using create-react-app and include the react-bootstrap, react-router, and axios libraries.
  • Strip out any unused code.
  • Follow the React Recipe.
  • Create component wireframes.
  • Create static components.
  • Components make API calls via a service.
  • Group components by resource.
  • Implement CSS Variables to reuse global styles

Here are the routes for the SPA:
/addresses - routes to the Addresses page which displays a list of addresses
/customers - routes to the Customers page which displays a list of customers, and a delete button next to each record
/customers/new - routes to the New Customer page, which displays a form to collect and submit data (including address information) for a new customer
/customers/:id - routes to the Customer Detail page which displays an individual customer’s personal information, along with the customer’s address, order history, and a delete button
/customers/:id/edit - routes to the Edit Customer page, which displays the customer whose information (including address) is being edited
/orders - routes to the Orders page, which displays a list of orders that can be filtered by their status, and a delete button next to each record
/orders/new - routes to the New Order page, which displays a list of all available products and a form to collect and submit data (including products) for a new order
/orders/:id - routes to the Order Detail page which displays an individual order’s information (including the products that are part of the order), and a delete button
/orders/:id/edit - routes to the Edit Order page, which displays the order whose information (including products) is being edited
/products - routes to the Products page, which displays a list of all available products and increment/decrement buttons for each product for inventory update purposes
/products/:id - routes to the Product Detail page, which displays information about a specific product and increment/decrement buttons

Stretch Goals: React Hooks, React Tests

User-story-8: Edit an existing customer

User-story-8: Edit an existing customer

As a CSR, I would like to edit an existing customer, so that I can keep customers’ information up-to-date in the system.

Acceptance Criteria:

Given that I am on the Edit Customer page,
And I see the existing customer information already pre-filled in the form,
When I make edits and submit the form,
Then I am redirected to the Customers page and see the updated customer in the list.

Requirements/Validations:

Frontend

  • Navigating to /customers/:id/edit should route the user to the Edit Customer page, which displays the customer whose information (including address) is being edited

Backend

  • If the operation is successful, the API endpoint PUT api/customers/:id will return a status code of 200 and a record of the edited customer as JSON (see the "Outputs" section below).

Inputs:

I will have the ability to provide new values for the following attributes:

  • first_name (string, required)
  • middle_name (string, optional)
  • last_name (string, required)
  • phone (string, required)
  • email (string, required)
  • notes (string, optional)

Outputs:

If the operation is successful, the API endpoint PUT api/customers/:id will return a status code of 200 and a record of the edited customer as JSON:

{
  "id": 1,
  "first_name": "Bernadine",
  "middle_name": "Ulysses",
  "last_name": "Ownsworth",
  "phone": "516-768-8190",
  "email": "[email protected]",
  "notes": "Curabitur convallis.",
  "address_id": 10
}

Recommended steps

  1. Create a simple wireframe (styles NOT needed) for the page.
  2. Determine what components are needed for the page
  3. Create the folder/files for the components, and create static components in each file.
  4. Set up the routes needed to route the user to the placeholder components
  5. Add state/props and other functionality to your components.
  6. Since your backend is not likely built yet while you're creating the front-end, you can add test data to db.json and use the fake json-server API instead.
  7. Build out the backend.
  8. Update the front-end to call the real backend API. Make sure everything works.
  9. When everything is working, style your application. Follow the style guide
  10. Refactor your code, as needed.

Resources

User-story-2: Create a new address

User-story-2: Create a new address

As a CSR, I would like to create a new address when a new customer calls in to place an order, so that I know where to ship the order.

Acceptance Criteria:

Given that I am on the New Address page,
When I submit a customer’s address using the form,
Then I am redirected to the Addresses page and see the new address being added to the list of existing customers

Requirements/Validations:

Frontend

  • Navigating to the /addresses/new path should route the user to the New Address page, which displays a form to collect and submit the address information for a new customer

Backend

  • If the operation is successful, the API endpoint POST api/customers should return a status code of 201 and a record of the newly added customer as JSON (see "Outputs" section below).

Inputs:

I can submit the following information:

  • Address line 1
  • Address line 2
  • City
  • State
  • zip

Outputs:

If the operation is successful, the API endpoint POST api/customers will return a status code of 201 and a record of the newly added customer as JSON:

{
  "id": 11,
  "address_line_1": "06 Memorial Junction",
  "address_line_2": "628",
  "city": "Belalong Kulon",
  "state": "CA",
  "zip": 18803
}

Recommended steps

  1. Create a simple wireframe (styles NOT needed) for the page.
  2. Determine what components are needed for the page
  3. Create the folder/files for the components, and create static components in each file.
  4. Set up the routes needed to route the user to the placeholder components
  5. Add state/props and other functionality to your components.
  6. Since your backend is not likely built yet while you're creating the front-end, you can add test data to db.json and use the fake json-server API instead.
  7. Build out the backend.
  8. Update the front-end to call the real backend API. Make sure everything works.
  9. When everything is working, style your application. Follow the style guide
  10. Refactor your code, as needed.

Resources

Create a style guide

Create a style guide

Goal

As a team, create a style guide that, at a minimum, should describe the visual identity of the application in terms of its:

  • Fonts
  • Colors
  • Logo
  • Icons/Images

Examples

Style Guide Samples

Steps

  • Read about what a style guide is
  • Divide into teams of 3/4. One team can be responsible for coming up with font suggestions. Another team focus on building out various color palettes. And another team can focus on the logo, images etc.
  • Come back together as a team and vote on the suggestions.
  • Have one person on the team be responsible for combining the work of various subteams into a final "Style Guide" that is added as a subsection to the front-end repo README.md.

User-story-11 Pagination for the Customers page

User-story-11 Pagination for the Customers page

As a CSR, I would like to view a list of the most recently added customers, so that I can follow up with them regarding their orders.

Acceptance Criteria:

Given that I am on the Customers page,
Whenever the page is loaded,
Then I see a list of the X most recently added customers
And I can click on a “Next” button to load the next X customers onto the page

Requirements/Validations:

Frontend:

  • The user should be able to select the number of customer records to load, up to 10, from a drop down menu
  • The “Next” button stays active until the user has paged through all the customers stored in the database

Backend

  • The API GET endpoint api/customers will return a status code of 200 and a set of customer record(s) that meet the search query as JSON (see the "Outputs" section below).

Inputs:

A query string

Outputs:

The API GET endpoint api/customers will return a status code of 200 and a set of customer record(s) that meet the search query as JSON.

Recommended steps

  1. Create a simple wireframe (styles NOT needed) for the page.
  2. Determine what components are needed for the page
  3. Create the folder/files for the components, and create static components in each file.
  4. Set up the routes needed to route the user to the placeholder components
  5. Add state/props and other functionality to your components.
  6. Since your backend is not likely built yet while you're creating the front-end, you can add test data to db.json and use the fake json-server API instead.
  7. Build out the backend.
  8. Update the front-end to call the real backend API. Make sure everything works.
  9. When everything is working, style your application. Follow the style guide
  10. Refactor your code, as needed.

Resources

User-story-12: List all orders

User-story-12: List all orders

As a CSR, I would like to view a list of the most recently added orders, so that I can help inform shipping on which products to prepare for shipping

Acceptance Criteria:

Given that I am on the Orders page,
Whenever the page is loaded,
Then I see a list of the orders (ordered from most to least recently added).

Requirements/Validations:

Frontend

  • Navigating to the /orders path should route the user to the Orders page, which displays a list of orders that can be filtered by their status
  • Display each order’s id, status, date/time the order was placed, and the customer’s first name, last name, and email address
  • Shipping/CSR can filter the order by status

Backend

  • The API endpoint GET api/orders should return a status code of 200 and a set of all orders record(s) as JSON (see the "Outputs" section below).

Inputs:

  • None

Outputs:

The API GET api/orders will return a status code of 200 and a set of all orders record(s) as JSON:

[{
  "id": 1,
  "customer_id": 51,
  "order_status": "lectus suspendisse potenti in eleifend quam a odio in hac habitasse platea dictumst maecenas",
  "datetime_order_placed": "2021-04-27 18:30:44",
  "total_order_price": 78,
  "order_notes": "Nulla tellus. In sagittis dui vel nisl. Duis ac nibh. Fusce lacus purus, aliquet at, feugiat non, pretium quis, lectus. Suspendisse potenti. In eleifend quam a odio."
}, {
  "id": 2,
  "customer_id": 30,
  "order_status": "molestie lorem quisque ut erat curabitur gravida nisi at nibh in hac habitasse platea dictumst aliquam augue quam sollicitudin vitae",
  "datetime_order_placed": "2020-12-03 23:56:55",
  "total_order_price": 80,
  "order_notes": "Vivamus vestibulum sagittis sapien. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Etiam vel augue. Vestibulum rutrum rutrum neque. Aenean auctor gravida sem. Praesent id massa id nisl venenatis lacinia. Aenean sit amet justo. Morbi ut odio. Cras mi pede, malesuada in, imperdiet et, commodo vulputate, justo. In blandit ultrices enim."
}, {
  "id": 3,
  "customer_id": 95,
  "order_status": "bibendum imperdiet nullam orci pede venenatis non sodales sed tincidunt eu felis fusce posuere felis sed lacus morbi sem",
  "datetime_order_placed": "2020-12-18 22:22:40",
  "total_order_price": 94,
  "order_notes": "Sed ante."
}, {
  "id": 4,
  "customer_id": 25,
  "order_status": "mi sit amet lobortis sapien sapien non mi integer ac neque duis bibendum morbi non quam",
  "datetime_order_placed": "2020-12-28 01:29:06",
  "total_order_price": 14,
  "order_notes": "Donec ut mauris eget massa tempor convallis. Nulla neque libero, convallis eget, eleifend luctus, ultricies eu, nibh. Quisque id justo sit amet sapien dignissim vestibulum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nulla dapibus dolor vel est. Donec odio justo, sollicitudin ut, suscipit a, feugiat et, eros."
}, {
  "id": 5,
  "customer_id": 18,
  "order_status": "vestibulum aliquet ultrices erat tortor sollicitudin mi sit amet lobortis sapien sapien",
  "datetime_order_placed": "2020-09-01 05:51:55",
  "total_order_price": 33,
  "order_notes": "Suspendisse ornare consequat lectus. In est risus, auctor sed, tristique in, tempus sit amet, sem. Fusce consequat. Nulla nisl. Nunc nisl."
}]

Recommended steps

  1. Create a simple wireframe (styles NOT needed) for the page.
  2. Determine what components are needed for the page
  3. Create the folder/files for the components, and create static components in each file.
  4. Set up the routes needed to route the user to the placeholder components
  5. Add state/props and other functionality to your components.
  6. Since your backend is not likely built yet while you're creating the front-end, you can add test data to db.json and use the fake json-server API instead.
  7. Build out the backend.
  8. Update the front-end to call the real backend API. Make sure everything works.
  9. When everything is working, style your application. Follow the style guide
  10. Refactor your code, as needed.

Resources

User-story-16: Delete an order

User-story-16: Delete an order

As a CSR, I would like to delete a draft order from the system, when I make a data entry mistake when entering an order.

Acceptance Criteria:

Given that I am on the Orders/Order Detail page,
And I see the list of existing orders,
When I press the delete button next to a record,
Then the order is deleted from the system and it no longer appears on the Orders page.

Requirements/Validations:

Frontend

  • On the Orders page at the /orders path or Order Detail page at the /orders/:id path, the user should see a delete button for for each order record.
  • When the Delete button is pressed, the CSR should see a confirmation modal asking the CSR to confirm that they indeed would like to delete the order. Clicking "Cancel" makes no changes, whereas clicking “Confirm” deletes the order and refreshes the list of orders on the page.
  • I should only be allowed to delete draft orders only, not live orders.

Backend

  • If the operation is successful, the API endpoint DELETE api/orders/:id should return a status code of 204

Inputs:

  • None

Outputs:

If the operation is successful, the API endpoint DELETE api/orders/:id will return a status code of 204.

Recommended steps

  1. Create a simple wireframe (styles NOT needed) for the page.
  2. Determine what components are needed for the page
  3. Create the folder/files for the components, and create static components in each file.
  4. Set up the routes needed to route the user to the placeholder components
  5. Add state/props and other functionality to your components.
  6. Since your backend is not likely built yet while you're creating the front-end, you can add test data to db.json and use the fake json-server API instead.
  7. Build out the backend.
  8. Update the front-end to call the real backend API. Make sure everything works.
  9. When everything is working, style your application. Follow the style guide
  10. Refactor your code, as needed.

Resources

User-story-3: Edit an existing address

User-story-3: Edit an existing address

As a CSR, I would like to edit an existing customer’s address whenever a customer calls in to update their address, so that I can ship their orders to the correct address.

Acceptance Criteria:

Given that I am on the Edit Customer page,
And I see the existing customer information already pre-filled in the form,
When I make edits to the address and submit the form,
Then I am redirected to the Customers page and see that the edited customer has an updated address id

Requirements/Validations:

Frontend

  • Navigating to the /addresses/:id/edit path should route the user to the Edit Address page, which displays the customer address that is being edited

Backend

  • The PUT api/addresses/:id endpoint should return a JSON output (see "Outputs" section below)

Inputs:

I will have the ability to provide new values for the following address fields:

  • Address line 1
  • Address line 2
  • City
  • State
  • zip

Outputs:

If the operation is successful, the API endpoint PUT api/customers/:id will return a status code of 200 and a record of the edited address as JSON:

{
  "id": 1,
  "address_line_1": "07 Memorial Junction",
  "address_line_2": "628",
  "city": "Bedadung Kulon",
  "state": "CA",
  "zip": 18803
}

Recommended steps

  1. Create a simple wireframe (styles NOT needed) for the page.
  2. Determine what components are needed for the page
  3. Create the folder/files for the components, and create static components in each file.
  4. Set up the routes needed to route the user to the placeholder components
  5. Add state/props and other functionality to your components.
  6. Since your backend is not likely built yet while you're creating the front-end, you can add test data to db.json and use the fake json-server API instead.
  7. Build out the backend.
  8. Update the front-end to call the real backend API. Make sure everything works.
  9. When everything is working, style your application. Follow the style guide
  10. Refactor your code, as needed.

Resources

User-story-15: Edit an existing order

User-story-15: Edit an existing order

As a CSR, I would like to edit an existing order whenever a customer calls in to edit an order or whenever the order status changes during the order lifecycle, so that I can track and keep the information for orders up-to-date in the system.

Acceptance Criteria:

Given that I am on the Edit Order page,
And I see the existing order information already pre-filled in the form,
When I make edits and submit the form,
Then I am redirected to the Orders page and see the updated order in the list.

Requirements/Validations:

Frontend

  • Navigating to the /orders/:id/edit path should route the user to the Edit Order page, which displays the order whose information (including products) is being edited
  • I can add or remove products from the order, the product count needs to be updated via the PUT api/products/:id endpoint
  • I can edit an order that has a status of Finalized, Preparing to Ship, Ready for Shipping
  • I can’t add a product that’s not available, and I see an error message when I try to do so
  • I can’t update the customer_id, or the date/time the order was placed.
  • I can’t edit an order that has already been shipped.
  • I can't close out an Order without confirmation that the Order arrived as expected.

Backend

  • If the operation is successful, the API endpoint PUT api/orders/:id should return a status code of 200 and a record of the edited customer as JSON (see the "Outputs" section below).

Inputs:

I will have the ability to provide new values for the following attributes:

  • order_status where the user can select an option from a dropdown menu that displays options for the possible statuses of the order (Draft/Open/Finalized/Preparing to ship/Ready for shipping/Shipped/Delivered/Closed)
  • order_notes

Outputs:

If the operation is successful, the API endpoint PUT api/orders/:id will return a status code of 200 and a record of the edited customer as JSON:

{
  "id": 5,
  "customer_id": 18,
  "order_status": "vestibulum aliquet ultrices erat tortor sollicitudin mi sit amet lobortis sapien sapien",
  "datetime_order_placed": "2020-09-01 05:51:55",
  "total_order_price": 33333,
  "order_notes": "Suspendisse ornare consequat lectus. In est risus, auctor sed, tristique in, tempus sit amet, sem. Fusce consequat. Nulla nisl. Nunc nisl."
}

Recommended steps

  1. Create a simple wireframe (styles NOT needed) for the page.
  2. Determine what components are needed for the page
  3. Create the folder/files for the components, and create static components in each file.
  4. Set up the routes needed to route the user to the placeholder components
  5. Add state/props and other functionality to your components.
  6. Since your backend is not likely built yet while you're creating the front-end, you can add test data to db.json and use the fake json-server API instead.
  7. Build out the backend.
  8. Update the front-end to call the real backend API. Make sure everything works.
  9. When everything is working, style your application. Follow the style guide
  10. Refactor your code, as needed.

Resources

User-story-14: Retrieve a specific order

User-story-14: Retrieve a specific order

As a CSR, I would like to view a specific order, so that I can gather information about the order.

Acceptance Criteria:

Given that I am on the Orders page,
When I click on an order in the list of orders,
Then I am redirected to the Order Detail page that displays the order’s information.

Requirements/Validations:

Frontend

  • Navigating to the /orders/:id path should route the user to the Order Detail page which displays an individual order’s information (including the products that are part of the order)
  • Display the customer’s first name, last name, email, phone, order status, the date/time the order was placed, and the order notes

Backend

  • The API GET api/orders/:id should return a status code of 200 and the specific order information as JSON (see the "Outputs" section below).

Inputs:

  • None

Outputs:

The API GET api/orders/:id will return a status code of 200 and the specific order information as JSON:

{
  "id": 5,
  "customer_id": 18,
  "order_status": "vestibulum aliquet ultrices erat tortor sollicitudin mi sit amet lobortis sapien sapien",
  "datetime_order_placed": "2020-09-01 05:51:55",
  "total_order_price": 33,
  "order_notes": "Suspendisse ornare consequat lectus. In est risus, auctor sed, tristique in, tempus sit amet, sem. Fusce consequat. Nulla nisl. Nunc nisl."
}

Recommended steps

  1. Create a simple wireframe (styles NOT needed) for the page.
  2. Determine what components are needed for the page
  3. Create the folder/files for the components, and create static components in each file.
  4. Set up the routes needed to route the user to the placeholder components
  5. Add state/props and other functionality to your components.
  6. Since your backend is not likely built yet while you're creating the front-end, you can add test data to db.json and use the fake json-server API instead.
  7. Build out the backend.
  8. Update the front-end to call the real backend API. Make sure everything works.
  9. When everything is working, style your application. Follow the style guide
  10. Refactor your code, as needed.

Resources

User-story-1: List all addresses

User-story-1: List all addresses

As a CSR, I would like to view a list of all customer addresses, so that I can keep shipping informed of where to ship products.

Acceptance Criteria:

Given that I am on the Addresses page,
Whenever the page is loaded,
Then I see a list of customer addresses (ordered by id).

Requirements/Validations:

  • Frontend
    • Navigating to the /addresses path routes the user to the Addresses page which displays a list of addresses
    • The page displays each address record’s id, address_line_1, address_line_2, city, state, and zip
  • Backend
    • The GET api/customers API endpoint should return a JSON output (see "Outputs" section below)

Recommended steps

  1. Create a simple wireframe (styles NOT needed) for the page.
  2. Determine what components are needed for the page
  3. Create the folder/files for the components, and create static components in each file.
  4. Set up the routes needed to route the user to the placeholder components
  5. Add state/props and other functionality to your components.
  6. Since your backend is not likely built yet while you're creating the front-end, you can add test data to db.json and use the fake json-server API instead.
  7. Build out the backend. Using code first, set up ONE table (addresses) in the database. Create the API endpoint to get all addresses.
  8. Update the front-end to call the real backend API. Make sure everything works.
  9. When everything is working, style your application. Follow the style guide
  10. Refactor your code, as needed.

Inputs:

None

Outputs:

The API GET api/addresses will return a status code of 200 and a set of all address record(s) as JSON:

[
    {
      "id": 1,
      "address_line_1": "06 Memorial Junction",
      "address_line_2": "628",
      "city": "Bedadung Kulon",
      "state": "CA",
      "zip": "18803"
    },
    {
      "id": 2,
      "address_line_1": "471 Basil Avenue",
      "address_line_2": "69084",
      "city": "Shijie",
      "state": "OH",
      "zip": "75070"
    },
    {
      "id": 3,
      "address_line_1": "3722 Toban Parkway",
      "address_line_2": "422",
      "city": "Plymouth",
      "state": "NY",
      "zip": "58317"
    },
    {
      "id": 4,
      "address_line_1": "6391 Linden Junction",
      "address_line_2": "3711",
      "city": "Głogówek",
      "state": "NJ",
      "zip": "10349"
    },
    {
      "id": 5,
      "address_line_1": "36 Cottonwood Parkway",
      "address_line_2": "71",
      "city": "Weitang",
      "state": "WA",
      "zip": "42744"
    }
  ]

Resources

User-story-18: Retrieve a specific product

User-story-18: Retrieve a specific product

As a CSR, I would like to view a specific product, so that I can gather information about the product.

Acceptance Criteria:

Given that I am on the Products page,
When I click on an order in the list of products,
Then I am redirected to the Product Detail page that displays the order’s information.

Requirements/Validations:

Frontend

  • Navigating to the /products/:id path should route the user to the Product Detail page, which displays information about a specific product

Backend

  • The API GET api/products/:id should return a status code of 200 and the specific order information as JSON (see "Outputs" section below).

Inputs:

  • None

Outputs:

The API GET api/products/:id will return a status code of 200 and the specific order information as JSON:

{
  "id": 5,
  "SKU": "9qmKkKw",
  "price": 26,
  "name": "a nibh in quis justo maecenas rhoncus aliquam lacus morbi quis tortor id nulla ultrices aliquet",
  "quantity": 90,
  "description": "Donec ut dolor. Morbi vel lectus in quam fringilla rhoncus. Mauris enim leo, rhoncus sed, vestibulum sit amet, cursus id, turpis. Integer aliquet, massa id lobortis convallis, tortor risus dapibus augue, vel accumsan tellus nisi eu orci. Mauris lacinia sapien quis libero."
}

Recommended steps

  1. Create a simple wireframe (styles NOT needed) for the page.
  2. Determine what components are needed for the page
  3. Create the folder/files for the components, and create static components in each file.
  4. Set up the routes needed to route the user to the placeholder components
  5. Add state/props and other functionality to your components.
  6. Since your backend is not likely built yet while you're creating the front-end, you can add test data to db.json and use the fake json-server API instead.
  7. Build out the backend.
  8. Update the front-end to call the real backend API. Make sure everything works.
  9. When everything is working, style your application. Follow the style guide
  10. Refactor your code, as needed.

Resources

User-story-6: Create a new customer

User-story-6: Create a new customer

As a CSR, I would like to create a customer record when a new customer calls in to place an order, so that I have relevant information about every customer.

Acceptance Criteria:

Given that I am on the New Customer page,
When I submit a customer’s information using the form,
Then I am redirected to the Customers page and see the new customer being added to the list of existing customers

Requirements/Validations:

Frontend

  • Navigating to the /customers/new path should route to the New Customer page, which displays a form to collect and submit data (including address information) for a new customer

Backend

  • I can only add the new customer if the customer does not already exist in the database (based on phone or email)
  • If the operation is successful, the API endpoint POST api/customers will return a status code of 201 and a record of the newly added customer as JSON (see the "Outputs" section below).

Inputs:

A customer record has the following attributes:

  • first_name (string, required)
  • middle_name (string, optional)
  • last_name (string, required)
  • phone (string, required)
  • email (string, required)
  • notes (string, optional)
  • address (dropdown menu loading the addresses that the CSR can choose from to associate with the customer)

Outputs:

If the operation is successful, the API endpoint POST api/customers will return a status code of 201 and a record of the newly added customer as JSON:

{
  "id": 1,
  "first_name": "Bernadine",
  "middle_name": "Ulysses",
  "last_name": "Ownsworth",
  "phone": "516-768-8190",
  "email": "[email protected]",
  "notes": "Curabitur convallis.",
  "address_id": 10
}

Recommended steps

  1. Create a simple wireframe (styles NOT needed) for the page.
  2. Determine what components are needed for the page
  3. Create the folder/files for the components, and create static components in each file.
  4. Set up the routes needed to route the user to the placeholder components
  5. Add state/props and other functionality to your components.
  6. Since your backend is not likely built yet while you're creating the front-end, you can add test data to db.json and use the fake json-server API instead.
  7. Build out the backend.
  8. Update the front-end to call the real backend API. Make sure everything works.
  9. When everything is working, style your application. Follow the style guide
  10. Refactor your code, as needed.

Resources

STRETCH GOAL:

Migrate real customer and address data into our database using the seeders.

Create wireframes

Split up into groups of 4 and create wireframes for the user stories:

  • User stories 1 - 4 (addresses): Ivy, Jefferson
  • User stories 5 - 11 (customers): Andre, Brittany, Dana
  • User stories 12 - 16 (orders): Tatyana, Johanny
  • User stories 17-19 (products): Joyce, Ning

Be prepared to present your wireframes to the front-end team.

Attach each wireframe to the corresponding user story.

Style the application

The overall goal here is to ensure that all pages on the website are styled consistently per the style guide.

User-story-13: Create a new order

User-story-13: Create a new order

As a CSR, I would like to create a new order when the customer calls in, so that I can store relevant information about every order.

Acceptance Criteria:

Given that I am on the New Order page,
Then I can select a customer for the order and the products to be added to the order,
And when I submit a customer’s order using the form,
Then I am redirected to the Orders page and see the new order being added to the list of existing orders

Requirements/Validations:

Frontend

  • Navigating to the /orders/new path should route the user to the New Order page, which displays a list of all available products and a form to collect and submit data (including products) for a new order
  • There must be an ability to save the order either as Draft, Open, or Finalized only
  • I can add or remove products from an order. I can only add one of each product per order.
  • I can’t add a product that’s not available, and I see an error message when I try to do so
  • When an order is finalized, I can mark the status as Finalized.

Backend

  • If the operation is successful, the API endpoint POST api/orders should return a status code of 201 and a record of the newly added customer as JSON (see the "Outputs" section below).

Inputs:

I can submit the following information:

  • customer_id (FK) of the customer to whom the order belongs
  • order_status where the CSR can select an option from a dropdown menu that displays options for the possible statuses of the order (Draft/Open/Finalized/Preparing to ship/Ready for shipping/Shipped/Delivered/Closed)
  • datetime_order_placed
  • total_order_price
  • order_notes
  • Products for the order

Outputs:

If the operation is successful, the API endpoint POST api/orders will return a status code of 201 and a record of the newly added customer as JSON:

{
  "id": 5,
  "customer_id": 18,
  "order_status": "vestibulum aliquet ultrices erat tortor sollicitudin mi sit amet lobortis sapien sapien",
  "datetime_order_placed": "2020-09-01 05:51:55",
  "total_order_price": 33,
  "order_notes": "Suspendisse ornare consequat lectus. In est risus, auctor sed, tristique in, tempus sit amet, sem. Fusce consequat. Nulla nisl. Nunc nisl."
}

Recommended steps

  1. Create a simple wireframe (styles NOT needed) for the page.
  2. Determine what components are needed for the page
  3. Create the folder/files for the components, and create static components in each file.
  4. Set up the routes needed to route the user to the placeholder components
  5. Add state/props and other functionality to your components.
  6. Since your backend is not likely built yet while you're creating the front-end, you can add test data to db.json and use the fake json-server API instead.
  7. Build out the backend.
  8. Update the front-end to call the real backend API. Make sure everything works.
  9. When everything is working, style your application. Follow the style guide
  10. Refactor your code, as needed.

Resources

User-story-4: Delete an address

User-story-4: Delete an address

As a CSR, I would like to delete a customer’s address from the system, so that the system is kept up-to-date with active customer addresses

Acceptance Criteria:

Given that I am on the Addresses page,
And I see the list of existing addresses,
When I press the delete button next to an address record,
Then the address record is deleted from the system and it no longer appears on the Addresses page.

Requirements/Validations:

Frontend

  • On the Addresses page, the CSR should see a delete button next to each address record.
  • When the Delete button is pressed, display a confirmation modal asking the CSR to confirm that they indeed would like to delete the address. Clicking "Cancel" makes no changes, whereas clicking “Confirm” deletes the customer record and refreshes the list of addresses on the page.

Backend

  • If the operation is successful, the API endpoint DELETE api/addresses/:id should return a status code of 204 (see the "Outputs" section below).

Inputs:

None

Outputs:

If the operation is successful, the API endpoint DELETE api/addresses/:id will return a status code of 204.

Recommended steps

  1. Create a simple wireframe (styles NOT needed) for the page.
  2. Determine what components are needed for the page
  3. Create the folder/files for the components, and create static components in each file.
  4. Set up the routes needed to route the user to the placeholder components
  5. Add state/props and other functionality to your components.
  6. Since your backend is not likely built yet while you're creating the front-end, you can add test data to db.json and use the fake json-server API instead.
  7. Build out the backend.
  8. Update the front-end to call the real backend API. Make sure everything works.
  9. When everything is working, style your application. Follow the style guide
  10. Refactor your code, as needed.

Resources

User-story-19: Update product inventory

User-story-19: Update product inventory

As a CSR, I would like to update each product’s inventory, so that I know whether or not a product is available for order.

Acceptance Criteria:

Given that I am on the Products or Product Detail page,
When I press the increment/decrement button for a product,
Then I see the updated product quantity for that product on the Products/Product Detail page.

Requirements/Validations:

Frontend

  • On the Products page at the /products path and on the Product Detail page at the /products/:id path, the user should see an increment/decrement button

Backend

  • If the operation is successful, the API endpoint PUT api/products/:id will return a status code of 200 and a record of the edited product as JSON (see "Outputs" section below):

Inputs:

I will have the ability to provide new values for the following attributes:

  • quantity

Outputs:

If the operation is successful, the API endpoint PUT api/products/:id will return a status code of 200 and a record of the edited product as JSON:

{
  "id": 5,
  "SKU": "9qmKkKw",
  "price": 26,
  "name": "a nibh in quis justo maecenas rhoncus aliquam lacus morbi quis tortor id nulla ultrices aliquet",
  "quantity": 80,
  "description": "Donec ut dolor. Morbi vel lectus in quam fringilla rhoncus. Mauris enim leo, rhoncus sed, vestibulum sit amet, cursus id, turpis. Integer aliquet, massa id lobortis convallis, tortor risus dapibus augue, vel accumsan tellus nisi eu orci. Mauris lacinia sapien quis libero."
}

Recommended steps

  1. Create a simple wireframe (styles NOT needed) for the page.
  2. Determine what components are needed for the page
  3. Create the folder/files for the components, and create static components in each file.
  4. Set up the routes needed to route the user to the placeholder components
  5. Add state/props and other functionality to your components.
  6. Since your backend is not likely built yet while you're creating the front-end, you can add test data to db.json and use the fake json-server API instead.
  7. Build out the backend.
  8. Update the front-end to call the real backend API. Make sure everything works.
  9. When everything is working, style your application. Follow the style guide
  10. Refactor your code, as needed.

Resources

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.