1. 你想我做? (做完比番你 / $)
2. 你想我做完話你知點做? (花時間 / $$)
3. 你想我經你隻手做? (花花花時間 / $$$)

有冇咩取向??

我唔係想同你打心理戰，但係我想知一知呢樣野先
10 個識等如全部識晒，咁你會比幾多個識比你自己?

我諗我會報 HKD 400 / phase

你用 mac ?
留一個聯絡方式?

ttps://t.me/louislabs/

留一留個 ec2 個登入方法?

thanks

Q: 我俾 pem key 同 elastic ip 你？
A: 可以呀，你經果頁 upload 比我 OK ?

揸定主意，用 nextjs 啦嘛


© 2024, Made with ❤️ by ThemeSelection
會唔會可以再簡單小小？例如唔洗右上嗰啲function?


### references
https://themeselection.com/item/materio-free-mui-nextjs-admin-template/

---

51.21.113.230

---

## Phase 2

### ASSIGNMENT MARKING CHECKLIST V1

#### PHASE 2A: SECURE SERVER SETUP (DEADLINE FEB.17, 2024) (SUBTOTAL: 5')

In this phase, you are required to set up a secure server for later development. Some guidance will be given in the tutorial.

1. Instantiate a free Virtual Cloud Machine (Amazon EC2 recommended or other free VPS) **\_** / 1'

- [ ] Details of the Free Usage Tier: http://aws.amazon.com/free
- [ ] You can apply for the education coupon on AWS
- [ ] With a Linux distribution, install only Ngnix, NodeJS and SQLite (or MySQL)
  - [ ] To minimize the attack surfaces, always install only what you need

1. Apply necessary security configurations **\_** / 2'

- [ ] Apply proper firewall settings to your VM: block all ports except 22, 80 and 443 only
- [ ] Apply proper updates for the server software packages in a regular manner
- [ ] Hide the versions of OS, Ngnix, and NodeJS in HTTP response headers

1. Configure the VM so that your website is accessible at http://sxx.ierg4210.ie.cuhk.edu.hk **\_** / 2'

- [ ] Apply for an elastic public IP, and ALWAYS associate it with the instantiated VM
- [ ] Submit your elastic IP through the provided Google Form link1 before 5pm, Feb 17, 2024
- [ ] TAs will then assign you a domain name and configure the DNS mapping for you
- [ ] Upload all your pages to the server. They should then be accessible through:
  - [ ] http://[your-own-public-IP], or
  - [ ] http://sxx.ierg4210.ie.cuhk.edu.hk

#### PHASE 2B: DATA PRESENTATION & MANAGEMENT (DEADLINE FEB. 25, 2024) (SUBTOTAL: 20')

In this phase, you will implement the core functions of the website mainly with NodeJS and SQL.

1. SQL: Create a database with the following structures (to be covered in the tutorial) **\_** / 1'

- [x] A table for `categories`
  - [x] Required columns:
    -[ ] [x] `cid` (primary key),
    -[ ] [x] `name`
  - [x] Data: at least 3 `categories` of your choice

- [x] A table for `products`
  - [x] Required columns:
    -[ ] [x] `pid (primary key)`,
    -[ ] [x] `cid`,
    -[ ] [x] `name`,
    -[ ] [x] `price`,
    -[ ] [x] `description`
  - [x] Data: at least 3 products for each category

1. HTML, NodeJS & SQL: Create an `admin panel`

   - [x] Design several HTML forms to manage(you can `insert`, `update` and `delete` information, `CRUD`) products in DB **\_** / 5'
       -[ ] [x] `insert`
       -[ ] [x] `update`
       -[ ] [x] `delete`
     -[ ] [x] Dropdown menu to select `cid` according to its name
     -[ ] [x] Input fields for inputting 
       -[ ] [x] `name`, 
       -[ ] [x] `price`
     -[ ] [x] Textarea for inputting `description`


   - [x] Design several HTML forms to manage `categories` in DB **\_** / 2'
     -[ ] [x] `insert`
     -[ ] [x] `update`
     -[ ] [x] `delete`

2. HTML, NodeJS, SQL: Update the ***main page*** created in Phase 1

   - [x] Populate the `category` list from DB **\_** / 1'
   - [x] Based on the `category` selected by the user, populate the corresponding product list from DB **\_** / 3'
     -[ ] [x] The `cid=[x]` is reflected as a query string in the URL
       -[ ] [x] 你想用邊種? 新做法我可以留番個註解比你 -> 新

3. HTML, NodeJS & SQL: Update the `product details` page created in Phase 1 **\_** / 2'

   - [x] Display the details of a product based on its DB record
   - [?] Display the inventory of a product based on its DB record

4. Support of automatic image resizing for product images **\_** / 3'
5. Supporting HTML5 Drag-and-drop file selection in the admin panel **\_** / 2'
   - [x] limit to upload jpg file

   - [x] File field for uploading an image (format: jpg/gif/png, size: <=5MB)
   - [/] For the file uploaded, store it with its name. **\_** / 1'
     -[ ] default to `my_path/image.jpg`

   - [?] When a large image is uploaded, the server will resize it and show a thumbnail image in the panel
   - [x] On the main page, display thumbnails. On the product description page, display the larger image

   - [?] Create a dropping area that takes an image
   - [?] Display a thumbnail (i.e. smaller width and height) if the dropped file is an image; reject it otherwise

### !!!CSRF

---

## PHASE 3

### AJAX SHOPPING LIST (DEADLINE: MAR 10, 2024) (SUBTOTAL: 13')

In this phase, you will implement the shopping list, which allows users to shop around your products. This phase is designed to let you practise Javascript programming.

1. JS: Dynamically update# the `shopping list`

   - [x] When the `addToCart` button of a product is clicked, add it to the shopping list **\_** / 1'
     -[ ] [x] Adding the same product twice will display only one row of record

   -  Once a product is added,
     -[ ] Users are allowed to 
       -[ ] [x] update its `quantity` and 
       -[ ] [x] delete it with a number input, or 
       -[ ] [x] two buttons for increment and decrement
     -[ ] [x] Store its 
       -[ ] [x] `pid` and 
       -[ ] [x] `quantity` in the browser's `localStorage` **\_** / 2'
     -[ ] [x] Get the 
       -[ ] [x] `name` and 
       -[ ] [x] `price` from the server (with `pid` as input) **\_** / 3'
     -[ ] [x] Calculate and display the `total amount` at the client-side **\_** / 1'

   - [x] Once the page is reloaded, the shopping list is restored **\_** / 2'
     -[ ] Page reloads when 
       -[ ] [x] users browse another category or 
       -[ ] [x] visit the product detail page
     -[ ] [x] Populate and retrieve the stored products from the `localStorage`

   - [?] Supporting infinite scroll when browsing products in the main page **\_** / 3'

<sub>#The whole process of shopping list management must be done without a page load</sub>

---



- aws setup swap file
  - https://repost.aws/knowledge-center/ec2-memory-swap-file


--- 

## phase 5

### Paypal Sandbox Accounts

1. Sign up at https://developer.paypal.com/dashboard/ : ______ / 1'
  a. Create two sandbox accounts – a merchant account and a buyer account:
    i. A merchant account – Email and Password
      sb-j4nbw29912003@business.example.com
      X<LqO7Sb

    ii. A buyer account – Email and Password
      sb-b00gb30304504@personal.example.com
      4s@0f>IE

  b. Create a sandbox application linked to the merchant account:
    i. an application – Client ID
      https://developer.paypal.com/dashboard/accounts/edit/4829534511909691981?accountName=sb-j4nbw29912003@business.example.com
      helloworld
      Client ID
      AQT5-eAKNK7IhAhBGlbHBu_9jBx74ZLCfEioKUWQMXMuMmLcnffmpoUz_z-ewOuKZmpSlDk74UtlH58O
      Secret key 1
      EMtwOzHACol7Tx8NHOa3eV3TPu2AerZEunJ3MBZfYYcxPeUDy-TNLqqcdL0UDQsrHMpQKeCRPcjKnwNy

#### Paypal Integration - Front End
Ref: 
  - https://developer.paypal.com/community/blog/how-to-add-paypal-checkout-payments-to-your-react-app/

2. Create a checkout button via PayPal standard checkout APIs: ______ / 1'
  a [x] Include the PayPal JavaScript SDK
  b [x] Set up a container element for the button
  c [x] Render the button by paypal.Buttons().render()
3. [x] When the checkout button is clicked, `createOrder()` is called: ______ / 3'
  a [x] every individual product (or any other data) to server.
    -[x] `name`
    -[x] `quantity`
  b [x] It waits for server to generate a JSON string named `orderDetails`.
    -[ ] refer backend `6.`
  c [x] It submits the order now to PayPal using the actions.order.create() function.
4 [x] After the buyer has completed the payment, `onApprove()` is called: ______ / 2'
  a [x] It passes the `orderDetails` to server.
  b [x] It clears the shopping cart.
5 [x] If the buyer cancels the payments, `onCancel()` is called: ______ / 1'
  a [x] It passes necessary information to server.


#### Paypal Integration - Back End

6. Server follows the following steps to generate the `orderDetails`: ______ / 5'
  a. server generates a digest that is the hash from a string composed of at least:
    -[x] of each selected product
      -[x] `name`
      -[x] `quantity`
    -[x] The `price` of each selected product gathered from DB,
    -[x] The `total price` of all selected products,
    -[x] `Currency code`,
    -[x] Merchant’s `email address`, and
    -[x] A `random salt`
  b.[x] server puts the generated digest in the `custom_id` of an order.
  c.[x] server generates an `UUID`, and puts it in the `invoice_id` of an order.
  d.[x] server generates other necessary fields of an order, including at least:
    -[x] `amount` - the `total price` and `currency code`
    -[x] `items` - the `name`, `quantity`, `price` of each selected item

7. Server follows the following steps to insert and update the DB orders table: ______ / 3'
  a. When `createOrder()` is called, it inserts a new entry:
    -[x] `UUID` - TEXT (Primary Key)
      - [x] custom_id
      - [x] invoice_id
    -[x] `username` - TEXT `customer's username`
    -[x] `digest` - TEXT, `custom_id`
    -[x] `salt` - TEXT
  b. [x] When `onApprove()` is called, it updates the corresponding entry:
    -[] `orderDetails` - TEXT
  c. [x] When `onCancel()` is called, it deletes the corresponding entry.

#### Miscellaneous Changes

8. [x] Display the DB orders table in the admin panel: product list, payment status…etc. ______ / 2'
9. [x] Let members check the most recent five orders in the member portal . ______ / 2'


### signal flow

#### Notes version:
```mermaid
sequenceDiagram
    actor Client
    
    Note left of Client: checkout button is clicked
    Note left of Client: `createOrder() is called

    Client->>Server:  fetch("/my-server/get-order-details"...

    Note over Server: generate `orderDetails`
    Server->>Client: return json `orderDetails`

    Note over Client: purchase_units: [amount, itesm, custom_id, invoice_id]

    Paypal-->>Client: send payment page
    Note over Client: Client proceed payment
    Client-->>Paypal: client approve payment

    Note over Client: When `onApprove()` is called
    Client->>Server: fetch("/my-server/save-order"...
    Note over Server: it `update` the corresponding entry

    Note over Client: When `onCancel()` is called
    Client->>Server: fetch("/my-server/cancel-order"...
    Note over Server: it `deletes` the corresponding entry
```


#### My version:
```mermaid
sequenceDiagram
    actor Client
    
    Note left of Client: checkout button is clicked
    Note left of Client: createOrder() is called

    Client->>Server:  fetch("/my-server/get-order-details"...

    Note over Server: generate `orderDetails`
    Server->>Client: return json `orderDetails`

    Note over Client: purchase_units: [amount, itesm, custom_id, invoice_id]

    Paypal-->>Client: send payment page
    Note over Client: Client proceed payment
    Client-->>Paypal: client approve payment

    Paypal->>Server: event_type: CHECKOUT.ORDER.APPROVED 
    Note left of Paypal: with (resources.id + resources.status)

    Note over Client: When `onApprove()` is called
    Client->>Server: fetch("/my-server/save-order"...
    Note right of Client: with resources.id

    Note over Server: receive 2 id, found match and stastus "approved"
    Note over Server: it `update` the corresponding entry

    Note over Client: When `onCancel()` is called
    Client->>Server: fetch("/my-server/cancel-order"...
    Note over Server: it `deletes` the corresponding entry
```
