āĻāϞā§āύ, āĻāĻ āĻāĻŽāϰāĻž āĻāĻāĻāĻž āϏāĻŋāύā§āĻŽāĻž āĻšāϞ āĻŦāĻžāύāĻžāĻŦā§ â āĻā§āĻĄ āĻĻāĻŋāϝāĻŧā§āĨ¤ đŦ
āĻāϝāĻŧ āĻĒāĻžāĻŦā§āύ āύāĻž, āĻĒāĻĒāĻāϰā§āύ āϞāĻžāĻāĻŦā§ āύāĻžāĨ¤ āĻāĻŋāύā§āϤ⧠āĻāĻāĻāĻž āĻāĻŋāύāĻŋāϏ āϞāĻžāĻāĻŦā§: āϧā§āϰā§āϝāĨ¤ āĻāĻžāϰāĻŖ āĻāĻŽāϰāĻž āĻļā§āϧ⧠āĻāĻāĻāĻž āĻŽā§āĻāĻŋ āϞāĻŋāϏā§āĻ āϏāĻžāĻāĻŋāϝāĻŧā§ āϰāĻžāĻāĻŦā§ āύāĻž â āĻāĻāĻāĻž āĻĒā§āϰ⧠Production-Grade Frontend Architecture āĻĻāĻžāĻāĻĄāĻŧ āĻāϰāĻžāĻŦā§, āĻāĻāĻĻāĻŽ āϏā§āĻā§āϰā§āϝāĻžāĻ āĻĨā§āĻā§āĨ¤ āĻĒā§āϞā§āϝāĻžāύāĻŋāĻ, āĻĄāĻŋāĻāĻžāĻāύ, āĻāĻŽā§āĻĒā§āύā§āύā§āĻ, āϏā§āĻā§āĻ āĻŽā§āϝāĻžāύā§āĻāĻŽā§āύā§āĻ â āϏāĻŦāĻāĻŋāĻā§āĨ¤
āϤāĻžāĻšāϞ⧠āϏā§āĻā§āϰāĻŋāύ⧠āĻā§āĻ āϰāĻžāĻā§āύ â āĻļā§āϰ⧠āĻāϰāĻž āϝāĻžāĻāĨ¤
Step 1: Movie Portal āĻāϏāϞ⧠āĻā§ āĻāĻŋāύāĻŋāϏ? đĨ
āĻā§āύ⧠āĻĒā§āϰāĻā§āĻā§āĻā§ āĻšāĻžāϤ āĻĻā§āĻāϝāĻŧāĻžāϰ āĻāĻā§ āϏāĻŦāĻā§āϝāĻŧā§ āĻāϰā§āϰāĻŋ āĻāĻžāĻāĻāĻž āĻšāϞ⧠â āĻĄā§āĻŽā§āĻāύ āĻŦā§āĻāĻžāĨ¤ āĻŽāĻžāύā§, āϝ⧠āĻĒā§āϰā§āĻĄāĻžāĻā§āĻāĻāĻž āĻāĻŽāϰāĻž āĻŦāĻžāύāĻžāϤ⧠āϝāĻžāĻā§āĻāĻŋ, āĻŦāĻžāϏā§āϤāĻŦā§ āϏā§āĻāĻž āĻā§ āĻāĻŦāĻ āĻā§āĻāĻžāĻŦā§ āĻāĻžāĻ āĻāϰ⧠â āĻāĻāĻž āύāĻž āĻŦā§āĻā§ āĻā§āĻĄ āϞāĻŋāĻāϤ⧠āĻŦāϏāĻž āĻŽāĻžāύ⧠āϏā§āĻā§āϰāĻŋāĻĒā§āĻ āύāĻž āĻĒāĻĄāĻŧā§āĻ āĻļā§āĻāĻŋāĻ āĻļā§āϰ⧠āĻāϰ⧠āĻĻā§āĻāϝāĻŧāĻžāĨ¤
"Movie Portal" āĻļāĻŦā§āĻĻāĻāĻž āĻļā§āύāϞ⧠āϏāĻžāϧāĻžāϰāĻŖāϤ āϝāĻž āĻŽāĻžāĻĨāĻžāϝāĻŧ āĻāϏ⧠āϤāĻž āĻšāϞā§:
āĻāĻŽāύ āĻāĻāĻāĻŋ āĻāϝāĻŧā§āĻŦāϏāĻžāĻāĻ āĻŦāĻž āĻ ā§āϝāĻžāĻĒ, āϝā§āĻāĻžāύ⧠āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰā§āϰāĻž āϏāĻŋāύā§āĻŽāĻž āĻā§āĻāĻā§ āĻĻā§āĻāϤ⧠āĻĒāĻžāϰā§, āϤāĻĨā§āϝ āĻāĻžāύāϤ⧠āĻĒāĻžāϰā§, āĻā§āϰā§āϞāĻžāϰ āĻĻā§āĻāϤ⧠āĻĒāĻžāϰ⧠â āĻāĻŦāĻ āĻāĻāύ⧠āĻāĻāύ⧠āϰā§āύā§āĻ āĻŦāĻž āϏā§āĻā§āϰāĻŋāĻŽāĻ āĻāϰāϤ⧠āĻĒāĻžāϰā§āĨ¤
āĻā§āĻāύāĻŋāĻā§āϝāĻžāϞ āĻāĻžāώāĻžāϝāĻŧ āĻŦāϞāϞā§, āĻāĻāĻž āĻāĻāĻāĻž content-catalog application â āϝāĻžāϰ āĻŽā§āϞ āĻāĻžāĻ āĻšāϞ⧠āĻāĻāĻāĻž structured dataset (āĻŽā§āĻāĻŋ āĻā§āϝāĻžāĻāĻžāϞāĻ)-āĻā§ browsable, searchable āĻāϰ interactive UI-āϤ⧠āϰā§āĻĒāĻžāύā§āϤāϰ āĻāϰāĻžāĨ¤ āĻāĻāĻāύ React developer āĻšāĻŋāϏā§āĻŦā§ āĻāĻĒāύāĻŋ āϝāĻĻāĻŋ āĻāĻāĻāĻž āĻāĻžāϞ⧠content catalog architecture āĻŦā§āĻā§ āĻĢā§āϞā§āύ, āϤāĻžāĻšāϞ⧠āĻ āύā§āĻ āϧāϰāύā§āϰ app āĻŦāĻžāύāĻžāύā§āϰ base āϤā§āϰāĻŋ āĻšā§ā§ āϝāĻžā§āĨ¤ āĻāϰ āϤāĻŋāύāĻāĻž āĻŽā§āϞ āĻŦāĻŋāϞā§āĻĄāĻŋāĻ āĻŦā§āϞāĻ:
- āĻāĻāĻāĻž data layer, āϝā§āĻāĻžāύ⧠āĻ āύā§āĻāĻā§āϞ⧠āϏāĻŋāύā§āĻŽāĻžāϰ āĻŽā§āĻāĻžāĻĄā§āĻāĻž (āύāĻžāĻŽ, āĻĒā§āϏā§āĻāĻžāϰ, āϰā§āĻāĻŋāĻ, āĻāĻŋāĻ, āĻĒā§āϰāĻžāĻāϏ) āĻāĻŽāĻž āĻĨāĻžāĻā§āĨ¤
- āĻāĻāĻāĻž discovery layer, āϝā§āĻāĻžāύ⧠āĻāĻāĻāĻžāϰ āϏāĻžāϰā§āĻ āĻāϰ āĻĢāĻŋāϞā§āĻāĻžāϰ āĻāϰāϤ⧠āĻĒāĻžāϰā§āĨ¤
- āĻāĻāĻāĻž detail/interaction layer, āϝā§āĻāĻžāύ⧠āĻāĻāĻāĻž āύāĻŋāϰā§āĻĻāĻŋāώā§āĻ āĻāĻāĻā§āĻŽā§āϰ āĻĄāĻŋāĻā§āĻāϞāϏ āĻĻā§āĻāĻž āϝāĻžāϝāĻŧ, āĻāϰ āĻ ā§āϝāĻžāĻāĻļāύ (āϝā§āĻŽāύ āĻāĻžāϰā§āĻā§ āϝā§āĻ āĻāϰāĻž) āύā§āĻāϝāĻŧāĻž āϝāĻžāϝāĻŧāĨ¤
āĻā§āύāĻž āĻāĻĻāĻžāĻšāϰāĻŖ: Netflix āĻāĻāĻāĻž Movie Portal (āϏāĻžāĻĨā§ Streaming Service-āĻ āĻŦāĻā§)āĨ¤ IMDB āĻāϰā§āĻāĻāĻž â āϝā§āĻāĻžāύ⧠āϤāĻĨā§āϝ, āĻā§āϰā§āϞāĻžāϰ, āϰā§āĻāĻŋāĻ, āϰāĻŋāĻāĻŋāĻ āϏāĻŦ āĻāĻ āĻāĻžāϝāĻŧāĻāĻžāϝāĻŧāĨ¤
đĩ āϤāĻžāĻšāϞ⧠āĻā§āĻ āϝāĻĻāĻŋ āĻŦāϞ⧠"Movie Portal Website āĻŦāĻžāύāĻžāĻ" â āϏāĻšāĻ āĻāĻžāώāĻžāϝāĻŧ āĻāϰ āĻŽāĻžāύ⧠āĻĻāĻžāĻāĻĄāĻŧāĻžāϝāĻŧ:
āĻāĻŽāύ āĻāĻāĻāĻž āĻāϝāĻŧā§āĻŦāϏāĻžāĻāĻ, āϝā§āĻāĻžāύ⧠āĻ āύā§āĻ āϏāĻŋāύā§āĻŽāĻžāϰ āϤāĻĨā§āϝ āĻĨāĻžāĻāĻŦā§, āĻāϰ āĻŽāĻžāύā§āώ āϏāĻšāĻā§āĻ āύāĻŋāĻā§āϰ āĻĒāĻāύā§āĻĻā§āϰ āϏāĻŋāύā§āĻŽāĻž āĻā§āĻāĻā§ āύāĻŋāϤ⧠āĻĒāĻžāϰāĻŦā§āĨ¤
āĻāĻŽāϰāĻž āĻāĻ āĻāĻŋāĻāĻā§āϰāĻŋāϝāĻŧāĻžāϞ⧠āϝā§āĻāĻž āĻŦāĻžāύāĻžāĻŦā§, āϏā§āĻāĻž āĻāĻāĻā§ āϏā§āĻĒā§āϏāĻŋāĻĢāĻŋāĻ â āĻāĻāĻāĻž Cinema Rental PortalāĨ¤ āĻŽāĻžāύ⧠āĻŽā§āĻāĻŋ āĻŦā§āϰāĻžāĻāĻ āĻāϰāĻž, āĻĄāĻŋāĻā§āĻāϞāϏ āĻĻā§āĻāĻž, āĻāϰ āĻāĻāĻāĻž Cart-āĻāĻŋāϤā§āϤāĻŋāĻ rental flow āĻĒāĻžāϰ āĻšāϝāĻŧā§ āϝāĻžāĻāϝāĻŧāĻžāĨ¤
Data Model â Fetch Data â Transform Data â Display Cards/List â Search + Filter + Sort â User Interaction
Step 2: āĻā§āĻĄ āϞā§āĻāĻžāϰ āĻāĻā§ â āϏā§āĻā§āϰāĻŋāĻĒā§āĻ āϰā§āĻĄāĻŋ āĻāϰā§āύ đ
āĻŦāĻĄāĻŧ āĻĄāĻŋāϰā§āĻā§āĻāϰāϰāĻž āĻļā§āĻāĻŋāĻ āĻļā§āϰ⧠āĻāϰāĻžāϰ āĻāĻā§ āĻĒā§āϰ⧠āϏā§āĻā§āϰāĻŋāĻĒā§āĻ, āϏā§āĻā§āϰāĻŋāĻŦā§āϰā§āĻĄ, āĻļāĻ-āϞāĻŋāϏā§āĻ āϰā§āĻĄāĻŋ āϰāĻžāĻā§āύāĨ¤ āĻĒā§āϰā§āĻā§āϰāĻžāĻŽāĻŋāĻāϝāĻŧā§āĻ āĻ āĻŋāĻ āĻāĻāĻ āύāĻŋāϝāĻŧāĻŽ â āĻā§āĻĄ āϞā§āĻāĻžāϰ āĻāĻā§ Requirement Analysis āĻāϰ System Design āύāĻž āĻāϰāϞā§, āĻĒāϰ⧠āĻāĻŋāϝāĻŧā§ Component re-architecture, state management āĻāĻ āĻāϰ technical debt-āĻāϰ āĻĒāĻžāĻšāĻžāĻĄāĻŧ āĻāĻŽā§ āϝāĻžāϝāĻŧāĨ¤ āĻāϰ āĻŦāĻŋāĻļā§āĻŦāĻžāϏ āĻāϰā§āύ, āĻŽāĻžāĻāĻĒāĻĨā§ āĻĒā§āϰ⧠āϏā§āĻ āĻā§āĻā§ āĻāĻŦāĻžāϰ āĻŦāĻžāύāĻžāύā§āϰ āĻā§āϝāĻŧā§ āĻāώā§āĻā§āϰ āĻāϰ āĻāĻŋāĻā§ āύā§āĻāĨ¤
ā§§. āĻĒā§āϰāĻā§āĻā§āĻā§āϰ āϏā§āĻā§āĻĒ āĻ āĻŋāĻ āĻāϰā§āύ
- App-āĻāϰ āĻāĻĻā§āĻĻā§āĻļā§āϝ āĻā§? (āĻŽā§āĻāĻŋ āĻŦā§āϰāĻžāĻāĻ āĻāϰāĻž, āϰā§āĻāĻŋāĻ āĻĻā§āĻāĻž, āϏāĻžāϰā§āĻ āĻāϰāĻž, āĻāĻžāϰā§āĻā§ āϝā§āĻ āĻāϰ⧠āϰā§āύā§āĻ āĻāϰāĻž)
- āĻĻāϰā§āĻļāĻ āĻāĻžāϰāĻž? āĻā§āύ āĻŦāϝāĻŧāϏā§āϰ, āĻā§āύ āĻĄāĻŋāĻāĻžāĻāϏ āĻĨā§āĻā§ āĻāϏāĻŦā§ â āĻŽā§āĻŦāĻžāĻāϞ-āĻĢāĻžāϰā§āϏā§āĻ āύāĻžāĻāĻŋ āĻĄā§āϏā§āĻāĻāĻĒ-āĻĢāĻžāϰā§āϏā§āĻ?
- Functional Requirements â āĻ ā§āϝāĻžāĻĒ āĻāϏāϞ⧠āĻā§ āĻā§ āĻāϰāϤ⧠āĻĒāĻžāϰāĻŦā§āĨ¤
- Non-Functional Requirements â āĻĒāĻžāϰāĻĢāϰāĻŽā§āϝāĻžāύā§āϏ, āϰā§āϏāĻĒāύāϏāĻŋāĻāύā§āϏ, āĻ ā§āϝāĻžāĻā§āϏā§āϏāĻŋāĻŦāĻŋāϞāĻŋāĻāĻŋāĨ¤
⧍. āĻĢāĻŋāĻāĻžāϰ āϞāĻŋāϏā§āĻ āĻ āĻāĻāĻāĻžāϰ āϏā§āĻā§āϰāĻŋ
āϤāĻžāĻĒāϏ āĻāĻžāĻ āĻāĻ āĻāĻŋāĻĄāĻŋāĻāϤ⧠āĻĻā§āĻāĻŋāϝāĻŧā§āĻā§āύ, āĻāĻāĻāĻž āϏāĻŋāύā§āĻŽāĻž āϰā§āύā§āĻāĻžāϞ āĻĒā§āϰā§āĻāĻžāϞ⧠āĻāϏāϞ⧠āĻā§ āĻā§ āĻĢāĻŋāĻāĻžāϰ āĻĨāĻžāĻāĻž āĻĻāϰāĻāĻžāϰ:
āĻĢāĻŋāĻāĻžāϰāĻā§āϞā§āĻā§ āĻļā§āϧ⧠āĻāĻāĻāĻž āϞāĻŋāϏā§āĻ āĻšāĻŋāϏā§āĻŦā§ āύāĻž āϰā§āĻā§ User Story āĻĢāϰāĻŽā§āϝāĻžāĻā§ āϞāĻŋāĻāϞ⧠āĻāĻāĻāĻž āĻŦāĻžāĻĄāĻŧāϤāĻŋ āϏā§āĻŦāĻŋāϧāĻž āĻĒāĻžāĻāϝāĻŧāĻž āϝāĻžāϝāĻŧ â āĻĒā§āϰāϤāĻŋāĻāĻž āĻĢāĻŋāĻāĻžāϰā§āϰ āĻĒā§āĻāύā§āϰ āĻā§āĻāύāĻŋāĻā§āϝāĻžāϞ āĻāĻžāĻšāĻŋāĻĻāĻžāĻāĻž (āĻā§āύ state, āĻā§āύ component āϞāĻžāĻāĻŦā§) āĻāĻā§āĻ āϏā§āĻĒāώā§āĻ āĻšāϝāĻŧā§ āϝāĻžāϝāĻŧ:
| Feature | User Story | Technical Implication |
|---|---|---|
| Movie Grid | āĻāĻāĻāύ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰ⧠āĻšāĻŋāϏā§āĻŦā§ āĻāĻŽāĻŋ āϏāĻŦ āĻŽā§āĻāĻŋ āĻāĻāĻāĻž āĻā§āϰāĻŋāĻĄā§ āĻĻā§āĻāϤ⧠āĻāĻžāĻ â āĻĒā§āϏā§āĻāĻžāϰ, āϰā§āĻāĻŋāĻ, āĻā§āϝāĻžāĻāĻžāĻāϰāĻŋ āĻ āĻĒā§āϰāĻžāĻāϏāϏāĻš | MovieGrid + MovieCard āĻāĻŽā§āĻĒā§āύā§āύā§āĻ, movies array-āϤ⧠.map() |
| Movie Details Modal | āĻāĻŽāĻŋ āϝā§āĻā§āύ⧠āĻŽā§āĻāĻŋ āĻāĻžāϰā§āĻĄā§ āĻā§āϞāĻŋāĻ āĻāϰ⧠āĻāϰ āĻŦāĻŋāϏā§āϤāĻžāϰāĻŋāϤ āĻŽāĻĄāĻžāϞ⧠āĻĻā§āĻāϤ⧠āĻāĻžāĻ | "selected movie" state, Modal āĻāĻŽā§āĻĒā§āύā§āύā§āĻ, createPortal |
| Add to Cart | āĻāĻŽāĻŋ āĻŽā§āĻāĻŋ āĻāĻžāϰā§āĻā§ āϝā§āĻ āĻāϰāϤ⧠āĻāĻžāĻ, āĻāĻā§ āĻĨā§āĻā§ āĻĨāĻžāĻāϞ⧠āĻāϝāĻŧāĻžāϰā§āύāĻŋāĻ āĻĒā§āϤ⧠āĻāĻžāĻ | Global Cart state (Context + Reducer), duplicate-check action |
| Cart Counter | āĻāĻžāϰā§āĻā§ āĻā§āϞāĻŋāĻ āĻāϰāϞ⧠āĻāĻŽāĻŋ āĻŽā§āĻāĻŋāϰ āύāĻžāĻŽ, āĻĒā§āϰāĻžāĻāϏ āĻ āϏāĻāĻā§āϝāĻž āĻĻā§āĻāϤ⧠āĻāĻžāĻ | Derived state â cart items āĻĨā§āĻā§ āĻāĻžāĻāύā§āĻ āĻ āĻā§āĻāĻžāϞ āĻĒā§āϰāĻžāĻāϏ āĻā§āϝāĻžāϞāĻā§āϞā§āĻ |
| Remove from Cart | āĻāĻŽāĻŋ āĻāĻžāϰā§āĻ āĻĨā§āĻā§ āĻŽā§āĻāĻŋ āϰāĻŋāĻŽā§āĻ āĻāϰāϤ⧠āĻāĻžāĻ, āϏāĻŦ āϰāĻŋāĻŽā§āĻ āĻāϰāϞ⧠empty message āĻĻā§āĻāϤ⧠āĻāĻžāĻ | REMOVE_FROM_CART reducer action, conditional rendering |
| Theme Switch | āĻāĻŽāĻŋ Light/Dark āĻĨāĻŋāĻŽā§āϰ āĻŽāϧā§āϝ⧠āĻāĻāϞ āĻāϰāϤ⧠āĻāĻžāĻ | Global Theme state (Context), localStorage persistence |
āĻĒā§āϰāĻĨāĻŽ āĻĒāϰā§āĻŦā§ āĻāĻŽāϰāĻž āĻāĻ āĻĢāĻŋāĻāĻžāϰāĻā§āϞā§āĻ āĻāĻāĻžāϰ āĻāϰāĻŦ:
- āĻŽā§āĻāĻŋ āϞāĻŋāϏā§āĻ āϰā§āύā§āĻĄāĻžāϰ āĻāϰāĻž â āĻĒā§āϰāϤāĻŋāĻāĻž āĻāĻžāϰā§āĻĄā§ āĻĢāĻā§, āϰā§āĻāĻŋāĻ, āĻā§āϝāĻžāĻāĻžāĻāϰāĻŋ āĻ āĻĒā§āϰāĻžāĻāϏ āĻĻā§āĻāĻžāύā§āĨ¤
- āĻā§āύ⧠āĻŽā§āĻāĻŋ āĻāĻžāϰā§āĻĄā§ āĻā§āϞāĻŋāĻ āĻāϰāϞ⧠āĻĄāĻŋāĻā§āĻāϞāϏ āĻŽāĻĄāĻžāϞ āĻĒāĻĒ-āĻāĻĒ āĻšāϝāĻŧā§ āĻĢā§āϞ āĻāύāĻĢā§ āĻĻā§āĻāĻžāύā§āĨ¤
- āĻāĻžāϰā§āĻ āĻŦāĻžāĻāύ⧠āĻā§āϞāĻŋāĻ āĻāϰāϞ⧠āĻŽā§āĻāĻŋ āĻāĻžāϰā§āĻā§ āϝā§āĻ āĻšāĻŦā§, āĻāĻžāĻāύā§āĻ +ā§§ āĻšāĻŦā§, āĻāĻā§ āĻĨā§āĻā§ āĻĨāĻžāĻāϞ⧠āĻāϝāĻŧāĻžāϰā§āύāĻŋāĻ āĻĻā§āĻāĻžāĻŦā§āĨ¤
- āĻāĻžāϰā§āĻ āĻĨā§āĻā§ āĻŽā§āĻāĻŋ āϰāĻŋāĻŽā§āĻ āĻāϰāĻžāϰ āĻĢāĻŋāĻāĻžāϰ â āϏāĻŦ āϰāĻŋāĻŽā§āĻ āĻšāϞ⧠empty message āĻĻā§āĻāĻžāĻŦā§āĨ¤
(Search, Watchlist, Review System, Login â āĻāĻā§āϞ⧠āĻĒāϰā§āϰ āϏāĻŋāĻāύā§āϰ āĻāύā§āϝ āϤā§āϞāĻž āĻĨāĻžāĻāϞ⧠đ)
ā§Š. UI/UX āĻĄāĻŋāĻāĻžāĻāύ āϰā§āĻĄāĻŋ āĻāϰā§āύ
āĻā§āϝāĻžāĻŽā§āϰāĻž āĻāĻžāϞāĻžāύā§āϰ āĻāĻā§ āϏā§āĻā§āϰāĻŋāĻŦā§āϰā§āĻĄ āϞāĻžāĻā§ â āĻ ā§āϝāĻžāĻĒā§āϰ āĻā§āώā§āϤā§āϰā§āĻ āϤāĻžāĻāĨ¤ Figma āĻŦāĻž āϝā§āĻā§āύ⧠āĻā§āϞ⧠āĻĢā§āϞ UI āĻĄāĻŋāĻāĻžāĻāύ āĻŦāĻžāύāĻžāύ, āύāĻŋāĻā§ āύāĻž āĻĒāĻžāϰāϞ⧠āĻĄāĻŋāĻāĻžāĻāύāĻžāϰā§āϰ āϏāĻžāĻšāĻžāϝā§āϝ āύāĻŋāύāĨ¤ āĻļā§āϰā§āϤā§āĻ āĻāĻāĻāĻž Design System (color tokens, spacing scale, typography scale) āĻ āĻŋāĻ āĻāϰ⧠āύāĻŋāϞ⧠āĻĒāϰ⧠Tailwind āĻāύāĻĢāĻŋāĻāĻžāϰā§āĻļāύ āĻāϰāĻžāĻāĻž āĻ āύā§āĻ āϏāĻšāĻ āĻšāϝāĻŧā§ āϝāĻžāϝāĻŧāĨ¤
āĻāĻ āĻ ā§āϝāĻžāĻĒā§āϰ āĻĄāĻŋāĻāĻžāĻāύ:
ā§§āĨ¤ Movie Portal Homepage
⧍āĨ¤ Movie Details Modal
ā§ŠāĨ¤ Cart Page
ā§ĒāĨ¤ Theme Switch UI
ā§Ē. āĻāĻŽā§āĻĒā§āύā§āύā§āĻ āĻŦā§āϰā§āĻāĻĄāĻžāĻāύ â UI-āĻā§ āĻā§āĻāϰ⧠āĻā§āĻāϰ⧠āĻāϰā§āύ
āĻĄāĻŋāĻāĻžāĻāύ āϰā§āĻĄāĻŋ āĻšāϝāĻŧā§ āĻā§āϞ⧠āĻĒāϰā§āϰ āĻāĻžāĻ â āĻĒā§āϰ⧠UI-āĻā§ āĻā§āĻ āĻā§āĻ, āϏā§āĻŦāĻžāϧā§āύ āĻ āĻāĻļā§ āĻāĻžāĻ āĻāϰāĻžāĨ¤ āĻāĻā§āĻ āĻŦāϞ⧠UI DecompositionāĨ¤ āĻŽā§āϞ āύā§āϤāĻŋ āĻāĻāĻāĻžāĻ â Single Responsibility: āĻĒā§āϰāϤāĻŋāĻāĻž āĻ āĻāĻļ āĻāĻāĻāĻž āύāĻŋāϰā§āĻĻāĻŋāώā§āĻ āĻāĻžāĻā§āϰ āĻāύā§āϝ āĻĻāĻžāϝāĻŧā§ āĻĨāĻžāĻāĻŦā§, āĻāϰ āĻĻāϰāĻāĻžāϰ āĻĒāĻĄāĻŧāϞ⧠āĻ āύā§āϝ āĻāĻžāϝāĻŧāĻāĻžāϤā§āĻ āϰāĻŋāĻāĻāĻ āĻāϰāĻž āϝāĻžāĻŦā§āĨ¤
āĻāĻĒāύāĻžāϰ āϏā§āĻā§āĻ UI-āĻā§ āĻāĻāĻžāĻŦā§ āĻā§āĻā§ āĻĢā§āϞā§āύ:
āϤāĻžāĻĒāϏ āĻāĻžāĻ āĻĻā§āĻāĻŋāϝāĻŧā§āĻā§āύ āĻā§āĻāĻžāĻŦā§ UI breakdown āĻāϰāϤ⧠āĻšāϝāĻŧ:
UI āĻĻā§āĻā§ āĻ āĻŋāĻ āĻāϰā§āύ āĻā§āύ āĻā§āύ āĻ āĻāĻļ āĻāϞāĻžāĻĻāĻž āĻāĻŽā§āĻĒā§āύā§āύā§āĻ āĻšāĻŦā§āĨ¤ (āϝā§āĻŽāύ: Header, Footer, MovieCard, SearchBar, Sidebar)
ā§Ģ. āĻāĻŽā§āĻĒā§āύā§āύā§āĻ āĻšāĻžāϝāĻŧāĻžāϰāĻžāϰā§āĻāĻŋ â āĻā§ āĻāĻžāϰ āĻā§āϤāϰ⧠āĻĨāĻžāĻāĻŦā§
Component Hierarchy āĻŽāĻžāύ⧠āĻšāϞ⧠â āĻā§āύ āĻāĻŽā§āĻĒā§āύā§āύā§āĻā§āϰ āĻā§āϤāϰ⧠āĻā§āύāĻāĻž āĻĨāĻžāĻāĻŦā§, āĻ āϰā§āĻĨāĻžā§ component tree-āϰ parent-child āϏāĻŽā§āĻĒāϰā§āĻ āĻ āĻŋāĻ āĻāϰāĻžāĨ¤ āĻāĻāĻžāĻ āĻĒāϰ⧠āĻ āĻŋāĻ āĻāϰ⧠āĻĻā§āĻŦā§ data āĻā§āύ āĻĻāĻŋāĻ āĻĨā§āĻā§ āĻā§āύ āĻĻāĻŋāĻā§ āϝāĻžāĻŦā§ â React-āĻ āĻĄā§āĻāĻž āϏāĻŦāϏāĻŽāϝāĻŧ unidirectional: āĻāĻĒāϰ āĻĨā§āĻā§ āύāĻŋāĻā§ props, āύāĻŋāĻ āĻĨā§āĻā§ āĻāĻĒāϰ⧠callback functionāĨ¤
āĻā§āύ āĻāĻŽā§āĻĒā§āύā§āύā§āĻā§āϰ āĻā§āϤāϰ⧠āĻā§āύāĻāĻž āĻĨāĻžāĻāĻŦā§, āϏā§āĻāĻž āĻāĻāĻāĻž Tree āĻāĻāĻžāϰ⧠āϏāĻžāĻāĻŋāϝāĻŧā§ āĻĢā§āϞā§āύāĨ¤ (App â Header, Main â Sidebar, MovieList â MovieCard)
āϤāĻžāĻĒāϏ āĻāĻžāĻ āĻĻā§āĻāĻŋāϝāĻŧā§āĻā§āύ āĻā§āĻāĻžāĻŦā§ Component Hierarchy āĻŦāĻžāύāĻžāϤ⧠āĻšāϝāĻŧ:
ā§Ŧ. Data Flow / State Planning
āĻĒā§āϰāϤāĻŋāĻāĻž React āĻĒā§āϰāĻā§āĻā§āĻā§ State-āĻā§ āϤāĻŋāύ āĻāĻžāĻā§ āĻāĻžāĻ āĻāϰ⧠āĻāĻžāĻŦāĻž āĻāĻāĻŋāϤ:
- Local UI State â āĻļā§āϧ⧠āĻāĻāĻāĻž āĻāĻŽā§āĻĒā§āύā§āύā§āĻā§āϰ āĻā§āϤāϰ⧠āĻĻāϰāĻāĻžāϰ (āϝā§āĻŽāύ: dropdown āĻā§āϞāĻž āĻāĻā§ āĻāĻŋāύāĻž)āĨ¤
useStateāĻĻāĻŋāϝāĻŧā§ āϏāĻžāĻŽāϞāĻžāύ⧠āϝāĻžāϝāĻŧāĨ¤ - Shared/Global State â āĻāĻāϏāĻžāĻĨā§ āĻāĻāĻžāϧāĻŋāĻ, āĻĻā§āϰ⧠āĻĻā§āϰ⧠āĻĨāĻžāĻāĻž āĻāĻŽā§āĻĒā§āύā§āύā§āĻā§āϰ āĻĻāϰāĻāĻžāϰ (Cart Items, Active Theme)āĨ¤ āĻāĻāĻžāύ⧠āĻāĻŽāϰāĻž Context + Reducer āĻĒā§āϝāĻžāĻāĻžāϰā§āύ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻŦ, āϝāĻžāϤ⧠prop drilling āĻāĻĄāĻŧāĻžāύ⧠āϝāĻžāϝāĻŧāĨ¤
- Derived State â āĻ āύā§āϝ state āĻĨā§āĻā§ āĻšāĻŋāϏāĻžāĻŦ āĻāϰ⧠āĻŦā§āϰ āĻāϰāĻž āϝāĻžāϝāĻŧ āĻāĻŽāύ āĻā§āϝāĻžāϞā§, āϝā§āĻŽāύ āĻāĻžāϰā§āĻā§āϰ āĻŽā§āĻ āĻĻāĻžāĻŽāĨ¤ āĻāĻā§āϞā§āĻā§ āĻāϞāĻžāĻĻāĻž state āĻšāĻŋāϏā§āĻŦā§ āύāĻž āϰā§āĻā§ render-āĻāϰ āϏāĻŽāϝāĻŧ calculate āĻāϰāĻžāĻ āĻāĻžāϞ⧠āĻ āĻā§āϝāĻžāϏāĨ¤
āĻā§āύ Data āĻā§āύ āĻāĻŽā§āĻĒā§āύā§āύā§āĻā§ āĻĻāϰāĻāĻžāϰ, āĻāϰ MovieData āĻā§āĻāĻžāĻŦā§ Cart-āĻ āĻĒā§āĻāĻāĻžāĻŦā§ â āϤāĻžāϰ āĻāĻāĻāĻž āϏāĻŽāϏā§āϝāĻž-āĻāĻŋāϤā§āϰ:
āĻāĻŽāĻžāĻĻā§āϰ āĻ
ā§āϝāĻžāĻĒā§: Movies List āĻāϰ Selected Movie Details āĻĨāĻžāĻāĻŦā§ component-local state āĻšāĻŋāϏā§āĻŦā§āĨ¤ āĻāϰ Cart Items āĻ Theme āĻĨāĻžāĻāĻŦā§ global Context-āĻ â āĻāĻžāϰāĻŖ Navbar (āĻāĻžāϰā§āĻ āĻāĻāĻāύā§āϰ āĻāύā§āϝ), MovieCard (Add to Cart āĻŦāĻžāĻāύā§āϰ āĻāύā§āϝ) āĻāϰ CartPage â āϤāĻŋāύāĻāύā§āϰāĻ āĻāĻāĻ cart data āĻĻāϰāĻāĻžāϰ, āĻ
āĻĨāĻ component tree-āϤ⧠āĻāϰāĻž āĻāĻā§ āĻ
āĻĒāϰ āĻĨā§āĻā§ āĻ
āύā§āĻ āĻĻā§āϰā§āĨ¤
ā§. Routes Planning (React Router)
āĻā§āύ āĻĒā§āĻā§ āĻā§ āĻĨāĻžāĻāĻŦā§, āϤāĻžāϰ āĻāĻāĻāĻž āĻŽā§āϝāĻžāĻĒ āĻĨāĻžāĻāĻž āĻĻāϰāĻāĻžāϰ â Modal-based UI āĻšāϞā§āĻāĨ¤ āĻāĻžāϰāĻŖ deep-linking (āϏāϰāĻžāϏāϰāĻŋ āĻāĻāĻāĻž URL āĻļā§āϝāĻŧāĻžāϰ āĻāϰ⧠āύāĻŋāϰā§āĻĻāĻŋāώā§āĻ āĻŽā§āĻāĻŋāϰ āĻĄāĻŋāĻā§āĻāϞāϏ āĻŦāĻž āĻāĻžāϰā§āĻ āĻā§āϞ⧠āϝāĻžāĻāϝāĻŧāĻž) āĻāĻāĻāĻž āϏāϞāĻŋāĻĄ UX āĻĒā§āϰā§āϝāĻžāĻāĻāĻŋāϏāĨ¤
(Route map: /, /movies/:id â :id āĻĨāĻžāĻāϞ⧠Movie Details Modal URL āĻĨā§āĻā§āĻ āĻā§āϞ⧠āϝāĻžāĻŦā§, /cart)
āĻāĻ āϰāĻžāĻāĻāĻŋāĻ āĻāĻŽāϰāĻž āĻĒāϰ⧠React Router v8 āĻĻāĻŋāϝāĻŧā§ āĻŦāϏāĻžāĻŦā§ (āĻāĻāύ āĻĒā§āϝāĻžāĻā§āĻā§āϰ āύāĻžāĻŽ āĻļā§āϧ⧠react-router â āĻāϞāĻžāĻĻāĻž āĻāϰ⧠react-router-dom āĻāύā§āϏāĻāϞ āĻāϰāĻžāϰ āĻĻāϰāĻāĻžāϰ āύā§āĻ)āĨ¤
ā§Ž. āĻĢā§āϞā§āĻĄāĻžāϰ āϏā§āĻā§āϰāĻžāĻāĻāĻžāϰ āĻĒā§āϞā§āϝāĻžāύ āĻāϰā§āύ
āĻĒā§āϰāĻā§āĻā§āĻā§āϰ āĻĢā§āϞā§āĻĄāĻžāϰ āĻā§āĻāĻžāĻŦā§ āϏāĻžāĻāĻžāĻŦā§āύ, āϏā§āĻāĻž āĻāĻā§āĻ āĻ āĻŋāĻ āĻāϰ⧠āύāĻŋāύāĨ¤ (components/, pages/, context/, data/, hooks/ āĻāϤā§āϝāĻžāĻĻāĻŋ) â āĻĒā§āϰ⧠āĻĢā§āϞā§āĻĄāĻžāϰ āϏā§āĻā§āϰāĻžāĻāĻāĻžāϰ āĻāĻŽāϰāĻž Step 3-āĻ āĻĄāĻŋāĻā§āĻāϞ⧠āĻĻā§āĻāĻŦāĨ¤
⥠āĻŦā§āύāĻžāϏ āĻāĻŋāĻĒāϏ
- Version Control: Git āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰā§āύāĨ¤ āĻŦāĻĄāĻŧ āĻā§āύ⧠āĻĒāϰāĻŋāĻŦāϰā§āϤāύā§āϰ āĻāĻā§ commit āĻāϰā§āύ, āĻāϰ āϏāĻŽā§āĻāĻŦ āĻšāϞ⧠Conventional Commits āĻĢāϰāĻŽā§āϝāĻžāĻ (
feat:,fix:,refactor:) āĻŽā§āύ⧠āĻāϞā§āύ â āĻĒāϰ⧠commit history āĻĒāĻĄāĻŧāϤ⧠āϏā§āĻŦāĻŋāϧāĻž āĻšāĻŦā§āĨ¤ - Documentation: āĻā§āĻĄā§āϰ āĻĒāĻžāĻļāĻžāĻĒāĻžāĻļāĻŋ āĻĄāĻā§āĻŽā§āύā§āĻā§āĻļāύāĻ āϰāĻžāĻā§āύāĨ¤ (README.md, āĻā§āĻĄā§ JSDoc āĻāĻŽā§āύā§āĻ)
āĻŦā§āϝāĻŦāĻšā§āϤ āĻā§āĻāύā§āϞāĻāĻŋ āĻ āĻāϰā§āĻāĻŋāĻā§āĻāĻāĻžāϰ đī¸
āĻāĻ Movie Portal āĻŦāĻžāύāĻžāϤ⧠āĻāĻŋāϝāĻŧā§ āĻāĻŽāϰāĻž āĻāϧā§āύāĻŋāĻ React Development-āĻāϰ āĻāϝāĻŧā§āĻāĻāĻž āĻā§āϰā§āϤā§āĻŦāĻĒā§āϰā§āĻŖ āϧāĻžāϰāĻŖāĻž āĻāĻžāĻā§ āϞāĻžāĻāĻžāĻŦā§āĨ¤
ā§§. Component-Based Architecture
React-āĻāϰ āϏāĻŦāĻā§āϝāĻŧā§ āĻļāĻā§āϤāĻŋāĻļāĻžāϞ⧠āĻāĻāĻĄāĻŋāϝāĻŧāĻžāĻā§āϞā§āϰ āĻāĻāĻāĻž āĻšāϞ⧠Component-Based Architecture â āĻĒā§āϰ⧠āĻ ā§āϝāĻžāĻĒāĻā§ āĻā§āĻ āĻā§āĻ, āĻĒā§āύāĻāĻŦā§āϝāĻŦāĻšāĻžāϰāϝā§āĻā§āϝ āĻāϰ āϏā§āĻŦāĻžāϧā§āύ UI āĻ āĻāĻļā§ āĻāĻžāĻ āĻāϰ⧠āĻĢā§āϞāĻžāĨ¤
āĻāĻŽāĻžāĻĻā§āϰ Movie Portal-āĻ āϝā§āĻŽāύ āĻāϞāĻžāĻĻāĻž āĻāĻŽā§āĻĒā§āύā§āύā§āĻ āĻĨāĻžāĻāĻŦā§:
Navbarâ āύā§āĻāĻŋāĻā§āĻļāύ āĻāϰ āĻāĻžāϰā§āĻ āĻāĻāĻāύMovieCardâ āĻāĻāĻāĻž āϏāĻŋāύā§āĻŽāĻžāϰ āϤāĻĨā§āϝ āĻĻā§āĻāĻžāύā§āϰ āĻāύā§āϝMovieGridâ āĻāĻāϏāĻžāĻĨā§ āĻ āύā§āĻ āϏāĻŋāύā§āĻŽāĻž āĻĻā§āĻāĻžāύā§āϰ āĻāύā§āϝMovieDetailsModalâ āĻāĻāĻāĻž āϏāĻŋāύā§āĻŽāĻžāϰ āĻŦāĻŋāϏā§āϤāĻžāϰāĻŋāϤ āϤāĻĨā§āϝSearchBarâ āϏāĻŋāύā§āĻŽāĻž āĻā§āĻāĻāĻžāϰ āĻāύā§āϝCartâ āĻāĻžāϰā§āĻā§ āĻĨāĻžāĻāĻž āĻŽā§āĻāĻŋāĻā§āϞ⧠āĻĻā§āĻāĻžāύā§āϰ āĻāύā§āϝ
āĻĢāϞāĻžāĻĢāϞ:
â Code Maintain āĻāϰāĻž āϏāĻšāĻ āĻšāϝāĻŧ â Component Reuse āĻāϰāĻž āϝāĻžāϝāĻŧ â Project Structure āĻĒāϰāĻŋāώā§āĻāĻžāϰ āĻĨāĻžāĻā§ â Development āĻĻā§āϰā§āϤ āĻšāϝāĻŧ
⧍. Component Mind Map & UI Planning
āĻŦāĻĄāĻŧ React Application-āĻ āĻšāĻžāϤ āĻĻā§āĻāϝāĻŧāĻžāϰ āĻāĻā§ Component Structure āĻĒā§āϞā§āϝāĻžāύ āĻāϰāĻžāĻāĻž āĻŽāĻžāϏā§āĻāĨ¤ Component Mind Map āĻĻāĻŋāϝāĻŧā§ āĻāĻŽāϰāĻž āĻ āĻŋāĻ āĻāϰāĻŋ â āĻā§āύ Component āϞāĻžāĻāĻŦā§, āĻāĻžāϰ āĻā§āϤāϰ⧠āĻā§ āĻĨāĻžāĻāĻŦā§, āĻāϰ āĻāĻžāϰ āĻĻāĻžāϝāĻŧāĻŋāϤā§āĻŦ āĻā§āĨ¤
MoviePortalApp
â
âââ Navbar (Cart Icon, Theme Toggle)
â
âââ HomePage
â â
â âââ SearchBar
â â
â âââ MovieGrid
â â
â âââ MovieCard
â
âââ MovieDetailsModal
â â
â âââ MovieInfo
â â
â âââ AddToCartButton
â
âââ CartPage
â
âââ CartItemāĻāĻ āĻŽā§āϝāĻžāĻĒāĻāĻžāĻ āĻāĻŽāĻžāĻĻā§āϰ UI āĻāϰ Data Flow āĻāĻā§ āĻĨā§āĻā§ āĻĒā§āϞā§āϝāĻžāύ āĻāϰāϤ⧠āϏāĻžāĻšāĻžāϝā§āϝ āĻāϰā§āĨ¤
ā§Š. Context API â Prop Drilling-āĻāϰ āϝāύā§āϤā§āϰāĻŖāĻž āĻĨā§āĻā§ āĻŽā§āĻā§āϤāĻŋ
Context API āĻšāϞ⧠React-āĻāϰ āĻŦāĻŋāϞā§āĻ-āĻāύ State Management āϏāϞāĻŋāĻāĻļāύāĨ¤ āϝāĻāύ āĻ āύā§āĻāĻā§āϞ⧠Component-āĻāϰ āĻāĻāĻ Data āĻĻāϰāĻāĻžāϰ āĻšāϝāĻŧ, āϤāĻāύ āĻāĻāĻžāĻ āĻŦāĻžāĻāĻāĻžāϝāĻŧāĨ¤
āϏāĻžāϧāĻžāϰāĻŖāϤ Parent āĻĨā§āĻā§ Child-āĻ Data āĻĒāĻžāĻ āĻžāϤ⧠āĻā§āϞ⧠āĻŦāĻžāϰāĻŦāĻžāϰ Props āĻĒāĻžāϏ āĻāϰāϤ⧠āĻšāϝāĻŧ â āĻāĻā§ āĻŦāϞ⧠Prop Drilling, āĻāϰ āĻāĻāĻž āϝāϤ āĻāĻā§āϰ⧠āϝāĻžāϝāĻŧ, āĻā§āĻĄ āϤāϤ āĻāϞā§āĻŽā§āϞ⧠āĻšāϝāĻŧā§ āĻāĻ ā§āĨ¤ Context API āĻāĻ āϏāĻŽāϏā§āϝāĻžāϰ āϏāĻŽāĻžāϧāĻžāύāĨ¤
āĻāĻŽāĻžāĻĻā§āϰ Movie Portal-āĻ Context API āĻĻāĻŋāϝāĻŧā§ āϝāĻž āϝāĻž āĻā§āϞā§āĻŦāĻžāϞāĻŋ āϰāĻžāĻāĻŦ:
- Cart Items āĻ Cart Actions
- Theme Settings (Light/Dark)
- Selected Movie (Modal-āĻāϰ āĻāύā§āϝ)
- Favorite Movies
- Authentication Status
Context Provider
â
âŧ
Multiple Components
â
âŧ
Access Shared Data via useContext()āĻĢāϞ⧠āϝā§āĻā§āύ⧠Component āĻĒā§āϰāĻĒ-āĻā§āĻāύ āύāĻž āĻā§āĻā§āĻ āϏāϰāĻžāϏāϰāĻŋ āĻĻāϰāĻāĻžāϰāĻŋ Data āĻ ā§āϝāĻžāĻā§āϏā§āϏ āĻāϰāϤ⧠āĻĒāĻžāϰā§āĨ¤
ā§Ē. Reducer Pattern (useReducer) â āĻāĻāĻŋāϞ State-āĻā§ āĻļā§āĻā§āĻāϞāĻžāϝāĻŧ āĻāύāĻž
Reducer Pattern-āĻ Complex State Logic āĻāĻāĻāĻž āĻāϞāĻžāĻĻāĻž pure function-āĻāϰ āĻšāĻžāϤ⧠āϤā§āϞ⧠āĻĻā§āĻāϝāĻŧāĻž āĻšāϝāĻŧāĨ¤ React-āĻāϰ useReducer Hook āĻĻāĻŋāϝāĻŧā§ āĻāĻāĻž implement āĻāϰāĻž āĻšāϝāĻŧ, āĻāϰ āĻāϰ āĻŽā§āϞ āĻāĻāĻĄāĻŋāϝāĻŧāĻž Redux āĻĨā§āĻā§āĻ āϧāĻžāϰ āĻāϰāĻž â State + Action + Reducer FunctionāĨ¤
Cart-āĻāϰ āĻāύā§āϝ āĻāĻŽāĻžāĻĻā§āϰ State shape āĻ Action:
const initialCartState = {
items: [], // [{ id, title, poster, price, qty }]
};Action:
{
type: "ADD_TO_CART",
payload: movie,
}Reducer:
function cartReducer(state, action) {
switch (action.type) {
case "ADD_TO_CART": {
const alreadyExists = state.items.some(
(item) => item.id === action.payload.id,
);
if (alreadyExists) {
return state; // duplicate āĻšāϞ⧠state āĻ
āĻĒāϰāĻŋāĻŦāϰā§āϤāĻŋāϤ āĻĨāĻžāĻāĻŦā§, UI warning āĻĻā§āĻāĻžāĻŦā§
}
return {
...state,
items: [...state.items, { ...action.payload, qty: 1 }],
};
}
case "REMOVE_FROM_CART":
return {
...state,
items: state.items.filter((item) => item.id !== action.payload.id),
};
default:
return state;
}
}Reducer āĻŦā§āϝāĻŦāĻšāĻžāϰā§āϰ āϏā§āĻŦāĻŋāϧāĻž:
â Complex State Logic āĻŽā§āϝāĻžāύā§āĻ āĻāϰāĻž āϏāĻšāĻ â State Update Predictable āĻšāϝāĻŧ (pure function â same input, same output āϏāĻŦāϏāĻŽāϝāĻŧ) â Code Scalable āĻšāϝāĻŧ â Large Application Maintain āĻāϰāĻž āϏāĻšāĻ āĻšāϝāĻŧ
āĻāĻ āĻĒā§āϰāĻā§āĻā§āĻā§ Component Architecture + Context API + Reducer Pattern â āĻāĻ āϤāĻŋāύā§āϰ āĻŽāĻŋāĻļā§āϞā§āĻ āĻāĻŽāϰāĻž āĻŦāĻžāύāĻžāĻŦā§ āĻāĻāĻāĻž Scalable, Maintainable Movie PortalāĨ¤ āĻāĻāύ āĻāϞā§āύ, āĻāĻāĻžāĻā§ āϏāϤā§āϝāĻŋ āϏāϤā§āϝāĻŋ āĻā§āĻĄā§ āϰā§āĻĒ āĻĻā§āĻāϝāĻŧāĻž āϝāĻžāĻ â Step 3āĨ¤
Step 3: āĻ ā§āϝāĻžāĻāĻļāύ! āĻā§āĻĄ āϞā§āĻāĻž āĻļā§āϰ⧠āĻāϰāĻŋ đŦ
HTML Template/UX āĻšāĻžāϤ⧠āĻĒā§āϝāĻŧā§ āĻā§āϞā§, āĻĒā§āϰāĻĨāĻŽ āĻāĻžāĻ â āϏā§āĻ markup-āĻā§ JSX-āĻ āϰā§āĻĒāĻžāύā§āϤāϰ āĻāϰ⧠āĻāĻŽā§āĻĒā§āύā§āύā§āĻ āĻŦāĻžāύāĻžāύā§āĨ¤ āĻāĻ āϧāĻžāĻĒā§ Step 2-āĻ āϝāĻž āĻĒā§āϞā§āϝāĻžāύ āĻāϰā§āĻāĻŋāϞāĻžāĻŽ (Component Breakdown, Context + Reducer, Routing), āϏāĻŦ āĻŦāĻžāϏā§āϤāĻŦā§ āϰā§āĻĒ āĻĻā§āĻŦ â āĻāĻāĻāĻž āĻĒā§āϰā§āĻĄāĻžāĻāĻļāύ-āĻā§āϰā§āĻĄ āϏā§āĻā§āϝāĻžāĻ āĻĻāĻŋāϝāĻŧā§: Vite 8 + React 19.2 + Tailwind CSS v4 + React Router v8āĨ¤
āϤāĻžāĻĒāϏ āĻāĻžāĻ āύāĻŋāĻā§āϰ āĻāĻŋāĻĄāĻŋāĻāϤ⧠āĻĻā§āĻāĻŋāϝāĻŧā§āĻā§āύ āĻā§āĻāĻžāĻŦā§ HTML āĻĨā§āĻā§ JSX-āĻ āϰā§āĻĒāĻžāύā§āϤāϰ āĻāϰāϤ⧠āĻšāϝāĻŧ, āĻāϰ āĻĢāĻā§/āĻāĻāĻāύ āĻā§āϞ⧠JSX-āĻ āĻā§āĻāĻžāĻŦā§ āĻŦāϏāĻžāϤ⧠āĻšāϝāĻŧ:
āĻāĻ āϧāĻžāĻĒā§āϰ āĻĒā§āϰ⧠āĻāϝāĻŧāĻžāϰā§āĻāĻĢā§āϞā§
ā§§āĨ¤ Vite āĻĻāĻŋāϝāĻŧā§ React āĻĒā§āϰāĻā§āĻā§āĻ āĻŦā§āĻāϏā§āĻā§āϰā§āϝāĻžāĻĒ āĻāϰāĻž āĻ Tailwind CSS v4 āĻāύā§āϏāĻāϞ āĻāϰāĻžāĨ¤
⧍āĨ¤ HTML template āĻĨā§āĻā§ JSX āϰā§āĻĒāĻžāύā§āϤāϰ, assets/icons āĻŽāĻžāĻāĻā§āϰā§āĻļāύāĨ¤
ā§ŠāĨ¤ Tailwind CSS v4-āĻāϰ CSS-first āĻāύāĻĢāĻŋāĻāĻžāϰā§āĻļāύ āϏā§āĻāĻāĻĒ (vite.config.js āĻ @theme āĻĄāĻŋāϰā§āĻā§āĻāĻŋāĻ)āĨ¤
ā§ĒāĨ¤ āĻĢā§āϞā§āĻĄāĻžāϰ āĻāϰā§āĻāĻŋāĻā§āĻāĻāĻžāϰ āĻĄāĻŋāĻāĻžāĻāύ āĻāϰ⧠āĻāĻā§ āĻāĻā§ āĻāĻŽā§āĻĒā§āύā§āύā§āĻ āĻŦāĻžāύāĻžāύā§āĨ¤
ā§ĢāĨ¤ data āĻĢā§āϞā§āĻĄāĻžāϰ āĻŦāĻžāύāĻŋāϝāĻŧā§ āĻŽā§āĻāĻŋ āĻĄā§āĻāĻž āĻšāĻžāϰā§āĻĄāĻā§āĻĄ āϰāĻžāĻāĻž (āĻĒāϰ⧠API āĻĻāĻŋāϝāĻŧā§ āϰāĻŋāĻĒā§āϞā§āϏ āĻāϰāĻžāϰ āĻāύā§āϝ āĻāĻāĻ shape āĻŽā§āύā§)āĨ¤
ā§ŦāĨ¤ CartContext āĻ useReducer āĻĻāĻŋāϝāĻŧā§ Cart āϏāĻŋāϏā§āĻā§āĻŽ implement āĻāϰāĻžāĨ¤
ā§āĨ¤ MovieDetailsModal āĻŦāĻžāύāĻžāύ⧠āĻāĻŦāĻ (āĻāĻā§āĻāĻŋāĻāĻāĻžāĻŦā§) React Router āĻĻāĻŋāϝāĻŧā§ URL-driven modal āĻŦāĻžāύāĻžāύā§āĨ¤
ā§ŽāĨ¤ ThemeContext āĻĻāĻŋāϝāĻŧā§ Light/Dark āĻĨāĻŋāĻŽ āϏā§āĻāĻāĻŋāĻ āĻŦāĻžāύāĻžāύā§āĨ¤
⧝āĨ¤ ESLint/Prettier āĻĻāĻŋāϝāĻŧā§ āĻā§āĻĄ āĻā§āϝāĻŧāĻžāϞāĻŋāĻāĻŋ āύāĻŋāĻļā§āĻāĻŋāϤ āĻāϰāĻžāĨ¤
āĻāϞā§āύ, āĻāĻā§ āĻāĻā§ āĻĸā§āĻā§ āĻĒāĻĄāĻŧāĻŋ āĻĒā§āϰāϤāĻŋāĻāĻž āϧāĻžāĻĒā§āĨ¤
āϧāĻžāĻĒ ā§§: Vite + React āĻĒā§āϰāĻā§āĻā§āĻ āĻŦā§āĻāϏā§āĻā§āϰā§āϝāĻžāĻĒ
Create React App (deprecated) āĻŦāĻžāĻĻ āĻĻāĻŋāϝāĻŧā§ āĻāĻŽāϰāĻž Vite āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻŦ â āĻāĻžāϰāĻŖ Vite āĻĄā§āĻā§āϞāĻĒāĻŽā§āύā§āĻā§ native ES modules āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰ⧠instant server start āĻāϰ Hot Module Replacement (HMR) āĻĻā§āϝāĻŧāĨ¤ āĻĒā§āϰā§āĻĄāĻžāĻāĻļāύ āĻŦāĻŋāϞā§āĻĄā§ āĻāĻāύ Rolldown (Rust-based unified bundler, Vite 8 āĻĨā§āĻā§ āĻĄāĻŋāĻĢāϞā§āĻ) āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻšāϝāĻŧ, āϝāĻž āĻāĻā§āϰ esbuild + Rollup dual-bundler āĻāϰā§āĻāĻŋāĻā§āĻāĻāĻžāϰāĻā§ āϰāĻŋāĻĒā§āϞā§āϏ āĻāϰ⧠āĻŦāĻŋāϞā§āĻĄ āϏā§āĻĒāĻŋāĻĄ āĻŦāĻšā§āĻā§āĻŖ āĻŦāĻžāĻĄāĻŧāĻŋāϝāĻŧā§ āĻĻāĻŋāϝāĻŧā§āĻā§āĨ¤
# Node.js 20.19+ āĻ
āĻĨāĻŦāĻž 22.12+ āĻĒā§āϰāϝāĻŧā§āĻāύ
npm create vite@latest movie-portal -- --template react
cd movie-portal
npm install
npm run devTypeScript āĻāĻžāĻāϞ⧠--template react-ts āĻĻāĻŋāύāĨ¤ āĻŦāĻĄāĻŧ āĻĒā§āϰāĻā§āĻā§āĻā§ āĻāĻžāĻāĻĒ āϏā§āĻĢāĻāĻŋ āĻ autocomplete-āĻāϰ āĻāύā§āϝ TypeScript āϰāĻŋāĻāĻŽā§āύā§āĻĄā§āĻĄ, āϤāĻŦā§ āĻāĻ āĻāĻŋāĻāĻā§āϰāĻŋāϝāĻŧāĻžāϞ⧠āĻāĻŽāϰāĻž plain JavaScript (JSX) āĻĻāĻŋāϝāĻŧā§ āĻāĻā§āĻŦā§ â āϝāĻžāϤ⧠āĻāύāϏā§āĻĒā§āĻāĻā§āϞ⧠āĻĒāϰāĻŋāώā§āĻāĻžāϰ āĻĨāĻžāĻā§, āĻāĻžāώāĻžāϰ āĻāĻāĻŋāϞāϤāĻžāϝāĻŧ āĻšāĻžāϰāĻŋāϝāĻŧā§ āύāĻž āϝāĻžāϝāĻŧāĨ¤
āϧāĻžāĻĒ ā§¨: Tailwind CSS v4 â āĻāύāĻĢāĻŋāĻāĻžāϰā§āĻļāύā§āϰ āύāϤā§āύ āύāĻŋāϝāĻŧāĻŽ
Tailwind CSS v4 āĻāĻāĻĻāĻŽ āĻā§āϰāĻžāĻāύā§āĻĄ-āĻāĻĒ āϰāĻŋāϰāĻžāĻāĻ â āĻāĻāύ āĻāĻāĻŋ Lightning CSS (Rust-based parser/transformer)-āĻāϰ āĻāĻĒāϰ āĻĻāĻžāĻāĻĄāĻŧāĻžāύā§āĨ¤ āϏāĻŦāĻā§āϝāĻŧā§ āĻŦāĻĄāĻŧ āĻĒāϰāĻŋāĻŦāϰā§āϤāύ: tailwind.config.js āĻĢāĻžāĻāϞ āĻāϰ āϞāĻžāĻā§ āύāĻž! āĻāύāĻĢāĻŋāĻāĻžāϰā§āĻļāύ āĻāĻāύ āϏāϰāĻžāϏāϰāĻŋ CSS āĻĢāĻžāĻāϞ⧠@theme āĻĄāĻŋāϰā§āĻā§āĻāĻŋāĻ āĻĻāĻŋāϝāĻŧā§ āĻšāϝāĻŧ (CSS-first configuration), āϝāĻž design token āĻā§āϞā§āĻā§ native CSS custom properties āĻšāĻŋāϏā§āĻŦā§ āĻāĻā§āϏāĻĒā§āĻ āĻāϰ⧠āĻĻā§āϝāĻŧāĨ¤
āĻĒā§āϰāĻĨāĻŽā§ first-party Vite āĻĒā§āϞāĻžāĻāĻŋāύāϏāĻš āĻāύā§āϏāĻāϞ āĻāϰā§āύ:
npm install tailwindcss @tailwindcss/vitevite.config.js-āĻ āĻĒā§āϞāĻžāĻāĻŋāύ āϝā§āĻ āĻāϰā§āύ:
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import tailwindcss from "@tailwindcss/vite";
export default defineConfig({
plugins: [react(), tailwindcss()],
});āĻāϰāĻĒāϰ src/index.css-āĻ āĻāĻāĻāĻž āĻāĻŽā§āĻĒā§āϰā§āĻ āϞāĻžāĻāύ āĻāϰ āĻāĻžāϏā§āĻāĻŽ āĻĨāĻŋāĻŽ āĻā§āĻā§āύ āϝā§āĻ āĻāϰā§āύ:
@import "tailwindcss";
@theme {
/* āĻāĻžāϏā§āĻāĻŽ āĻāĻžāϞāĻžāϰ â āĻāĻŽāĻžāĻĻā§āϰ āĻĄāĻŋāĻāĻžāĻāύ āϏāĻŋāϏā§āĻā§āĻŽ āĻā§āĻā§āύ */
--color-primary: #ff0000;
--color-secondary: #00ff00;
/* āĻāĻžāϏā§āĻāĻŽ āĻĢāύā§āĻ āĻ āϏā§āĻĒā§āϏāĻŋāĻ āϏā§āĻā§āϞ-āĻ āĻāĻāĻžāύā§āĻ āϝā§āĻ āĻāϰāĻž āϝāĻžāĻŦā§ */
--font-display: "Hind Siliguri", sans-serif;
}
/* Dark mode variant â v4-āϤ⧠darkMode āĻāϰ JS config-āĻ āĻĨāĻžāĻā§ āύāĻž */
@custom-variant dark (&:where(.dark, .dark *));āĻŽāĻāĻžāϰ āĻŦā§āϝāĻžāĻĒāĻžāϰ āĻšāϞ⧠â --color-primary āĻĄāĻŋāĻĢāĻžāĻāύ āĻāϰāĻžāϰ āϏāĻžāĻĨā§ āϏāĻžāĻĨā§āĻ Tailwind āύāĻŋāĻā§ āĻĨā§āĻā§ bg-primary, text-primary, border-primary āĻāϤā§āϝāĻžāĻĻāĻŋ āĻā§āϞāĻžāϏ āĻā§āύāĻžāϰā§āĻ āĻāϰ⧠āĻĻā§āϝāĻŧāĨ¤ āĻāϞāĻžāĻĻāĻž āĻāϰ⧠colors: { primary: ... } āϞāĻŋāĻā§ extend āĻāϰāĻžāϰ āĻĻāϰāĻāĻžāϰāĻ āύā§āĻāĨ¤
Container utility āĻāĻžāϏā§āĻāĻŽāĻžāĻāĻā§āĻļāύ: v3-āϤā§
container: { center: true, padding: "2rem" }āϝā§āĻāĻžāĻŦā§ JS āĻ āĻŦāĻā§āĻā§āĻā§ āϞā§āĻāĻž āĻšāϤā§, v4-āϤ⧠āϏā§āĻāĻž@utilityāĻĄāĻŋāϰā§āĻā§āĻāĻŋāĻ āĻĻāĻŋāϝāĻŧā§ override āĻāϰāϤ⧠āĻšāϝāĻŧ:
@utility container {
margin-inline: auto;
padding-inline: 2rem;
}v4 āĻĻā§āϰā§āϤ evolve āĻāϰāĻā§, āϤāĻžāĻ āϏāϰā§āĻŦāĻļā§āώ āϏāĻŋāύāĻā§āϝāĻžāĻā§āϏā§āϰ āĻāύā§āϝ āĻ āĻĢāĻŋāϏāĻŋāϝāĻŧāĻžāϞ Tailwind CSS āĻĄāĻā§āĻŽā§āύā§āĻā§āĻļāύ āĻāĻāĻŦāĻžāϰ āĻā§āĻ āĻāϰ⧠āύā§āĻāϝāĻŧāĻžāĻ āĻŦā§āĻĻā§āϧāĻŋāĻŽāĻžāύā§āϰ āĻāĻžāĻāĨ¤
āϧāĻžāĻĒ ā§Š: HTML Template āĻĨā§āĻā§ JSX â āĻ āύā§āĻŦāĻžāĻĻā§āϰ āύāĻŋāϝāĻŧāĻŽāĻāĻžāύā§āύ
HTML markup-āĻā§ JSX-āĻ āϰā§āĻĒāĻžāύā§āϤāϰā§āϰ āϏāĻŽāϝāĻŧ āĻāĻŋāĻā§ āϏāĻŋāύāĻā§āϝāĻžāĻā§āϏ āύāĻŋāϝāĻŧāĻŽ āĻŽāύ⧠āϰāĻžāĻāϤ⧠āĻšāϝāĻŧ, āĻāĻžāϰāĻŖ JSX āĻāϏāϞ⧠HTML āύāϝāĻŧ â āĻāĻāĻž JavaScript-āĻāϰāĻ āϏāĻŋāύāĻā§āϝāĻžāĻā§āĻāĻŋāĻ āϏā§āĻāĻžāϰ (āĻĒā§āĻāύ⧠āĻāĻŋāϝāĻŧā§ React.createElement() āĻāϞ⧠āĻāĻŽā§āĻĒāĻžāĻāϞ āĻšāϝāĻŧ):
classâclassName(āĻāĻžāϰāĻŖclassJavaScript-āĻāϰ reserved keyword)forâhtmlFor(āϞā§āĻŦā§āϞ āĻāϞāĻŋāĻŽā§āύā§āĻā§)- inline
styleāϏā§āĻā§āϰāĻŋāĻ āύāĻž āĻšāϝāĻŧā§ JavaScript object āĻšāĻŦā§, āĻĒā§āϰāĻĒāĻžāϰā§āĻāĻŋ āύā§āĻŽ camelCase:style={{ backgroundColor: "#000", marginTop: "10px" }} - āϏāĻŦ attribute camelCase:
onclickâonClick,tabindexâtabIndex,readonlyâreadOnly - Self-closing void elements:
<img>,<input>,<br>āĻ āĻŦāĻļā§āϝāĻ self-close āĻāϰāϤ⧠āĻšāĻŦā§ â<img src="..." /> - Comment syntax: HTML āĻāĻŽā§āύā§āĻ (
<!-- -->)-āĻāϰ āĻŦāĻĻāϞā§{/* comment */} - JavaScript expression embedding: āĻāĻžāϰā§āϞāĻŋ āĻŦā§āϰā§āϏ
{}āĻĻāĻŋāϝāĻŧā§ dynamic āĻā§āϝāĻžāϞ⧠āĻŦāϏāĻžāύ⧠āĻšāϝāĻŧ â<h1>{movie.title}</h1> - āĻāĻāĻāĻžāĻ root element: āĻĒā§āϰāϤāĻŋāĻāĻž āĻāĻŽā§āĻĒā§āύā§āύā§āĻ āĻāĻāĻāĻž single root return āĻāϰāĻŦā§ â āĻŦāĻžāĻĄāĻŧāϤāĻŋ wrapper
<div>āĻāĻĄāĻŧāĻžāϤā§<>...</>(Fragment) āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻž āϝāĻžāϝāĻŧ - List rendering-āĻ
keyprop:.map()āĻĻāĻŋāϝāĻŧā§ āϞā§āĻĒ āĻāϰāĻžāϰ āϏāĻŽāϝāĻŧ āĻĒā§āϰāϤāĻŋāĻāĻž child-āĻ āĻāĻāύāĻŋāĻkeyāĻĻāĻŋāϤā§āĻ āĻšāĻŦā§ âmovies.map((m) => <MovieCard key={m.id} movie={m} />)
Assets āĻ āĻāĻāĻāύ āĻŽāĻžāĻāĻā§āϰā§āĻļāύ:
HTML template-āĻāϰ assets/images, assets/fonts, assets/icons āĻĢā§āϞā§āĻĄāĻžāϰāĻā§āϞ⧠src/assets-āĻ āĻāĻĒāĻŋ āĻāϰā§āύāĨ¤ Vite-āĻ āĻĻā§āĻ āϰāĻāĻŽ asset handling āĻāĻā§:
-
src/assets-āĻ āϰāĻžāĻāĻž āĻĢāĻžāĻāϞimportāĻāϰ⧠āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāϤ⧠āĻšāϝāĻŧ â Vite āĻāĻā§āϞā§āĻā§ build-time-āĻ hash āĻāϰā§, optimize āĻāϰ⧠bundle-āĻ āĻĸā§āĻāĻŋāϝāĻŧā§ āĻĻā§āϝāĻŧ:import heroBanner from "../assets/images/hero-banner.jpg"; <img src={heroBanner} alt="Hero banner" />; -
public/āĻĢā§āϞā§āĻĄāĻžāϰā§āϰ āĻĢāĻžāĻāϞ āĻĒā§āϰāϏā§āϏ āĻšāϝāĻŧ āύāĻž, āϏāϰāĻžāϏāϰāĻŋ root path āĻĻāĻŋāϝāĻŧā§ āϰā§āĻĢāĻžāϰ āĻāϰāĻž āĻšāϝāĻŧ (favicon, robots.txt āĻāϤā§āϝāĻžāĻĻāĻŋ)āĨ¤
āĻāĻāĻāύā§āϰ āĻā§āώā§āϤā§āϰ⧠raw SVG āĻĢāĻžāĻāϞ āĻāĻĒāĻŋ āύāĻž āĻāϰ⧠lucide-react-āĻāϰ āĻŽāϤ⧠tree-shakeable, component-based icon library āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻž āĻ
āύā§āĻ āĻŦā§āĻļāĻŋ āĻŽā§āĻāύāĻā§āĻāύā§āĻŦāϞ:
npm install lucide-reactimport { ShoppingCart, Star, Sun, Moon } from "lucide-react";
<button>
<ShoppingCart size={20} className="text-primary" />
</button>;āϧāĻžāĻĒ ā§Ē: āĻĢā§āϞā§āĻĄāĻžāϰ āĻāϰā§āĻāĻŋāĻā§āĻāĻāĻžāϰ āĻ āĻāĻŽā§āĻĒā§āύā§āύā§āĻ āϤā§āϰāĻŋ
āϏā§āĻā§āϞā§āĻŦāϞ āĻĒā§āϰāĻā§āĻā§āĻā§āϰ āĻāύā§āϝ āĻāĻŽāϰāĻž feature-based āĻĢā§āϞā§āĻĄāĻžāϰ āϏā§āĻā§āϰāĻžāĻāĻāĻžāϰ āĻĢāϞ⧠āĻāϰāĻŦ:
src/
âââ assets/ # images, fonts, raw svg
âââ components/
â âââ ui/ # Button, Badge, Modal â āĻĒā§āύāĻāĻŦā§āϝāĻŦāĻšāĻžāϰāϝā§āĻā§āϝ āĻĒā§āϰāĻŋāĻŽāĻŋāĻāĻŋāĻ
â âââ layout/ # Navbar, Footer
â âââ movies/ # MovieCard, MovieGrid, MovieDetailsModal
âââ context/ # ThemeContext, CartContext
âââ data/ # hardcoded mock data
âââ hooks/ # useTheme, useCart, custom hooks
âââ pages/ # HomePage, CartPage
âââ lib/ # utils, helper functions
âââ App.jsx
âââ main.jsx
âââ index.cssāĻāĻŽā§āĻĒā§āύā§āύā§āĻ āĻŦāĻžāύāĻžāύā§āϰ āϏāĻŽāϝāĻŧ āĻāĻŽāϰāĻž āĻāĻŋāĻā§ āύā§āϤāĻŋ āĻŽāĻžāĻĨāĻžāϝāĻŧ āϰāĻžāĻāĻŦ:
- Single Responsibility â āĻĒā§āϰāϤāĻŋāĻāĻž āĻāĻŽā§āĻĒā§āύā§āύā§āĻ āĻāĻāĻāĻžāĻ āĻāĻžāĻ āĻāϰāĻŦā§ (
MovieCardāĻļā§āϧ⧠āĻāĻāĻāĻž āĻŽā§āĻāĻŋāϰ āĻāĻžāϰā§āĻĄ āĻĻā§āĻāĻžāĻŦā§, cart logic āϤāĻžāϰ āĻĻāĻžāϝāĻŧāĻŋāϤā§āĻŦ āύāĻž)āĨ¤ - Composition over prop drilling â āĻāĻā§āϰ component tree-āϤ⧠āĻŦāĻžāϰāĻŦāĻžāϰ props āύāĻž āĻĒāĻžāĻ āĻŋāϝāĻŧā§ Context API āĻŦā§āϝāĻŦāĻšāĻžāϰāĨ¤
- Presentational vs Container split â
MovieCardāĻļā§āϧ⧠UI āĻĻā§āĻāĻžāĻŦā§ (presentational), āĻāϰ actual cart action āĻāϏāĻŦā§useCart()hook āĻĨā§āĻā§ (container logic āĻšā§āĻā§ āĻŦāύā§āĻĻāĻŋ)āĨ¤ - React 19.2-āĻāϰ React Compiler (āĻāĻāύ⧠opt-in,
@vitejs/plugin-reactv6-āĻāϰ āϏāĻžāĻĨā§ babel/Oxc āĻĒā§āϰāĻŋāϏā§āĻ āĻĻāĻŋāϝāĻŧā§ āĻāύāĻžāĻŦāϞ āĻāϰāĻž āϝāĻžāϝāĻŧ) āĻāĻŽā§āĻĒā§āύā§āύā§āĻāĻā§āϞā§āĻā§ āĻ āĻā§āĻŽā§āĻāĻŋāĻā§āϝāĻžāϞāĻŋ āĻŽā§āĻŽā§āϝāĻŧāĻžāĻāĻ āĻāϰ⧠āĻĻā§āϝāĻŧ â āĻĢāϞ⧠āĻŦā§āĻļāĻŋāϰāĻāĻžāĻ āĻā§āώā§āϤā§āϰ⧠āĻŽā§āϝāĻžāύā§āϝāĻŧāĻžāϞāĻŋuseMemo/useCallbackāĻāĻĄāĻŧāĻŋāϝāĻŧā§ āĻĻā§āĻāϝāĻŧāĻžāϰ āĻĻāϰāĻāĻžāϰ āĻāĻŽā§ āĻāϏā§āĨ¤ āϤāĻŦā§ āĻāĻāĻž āĻāĻāύ⧠maturing āϏā§āĻā§āĻā§, āϤāĻžāĻ āĻĒā§āϰā§āĻĄāĻžāĻāĻļāύ⧠āĻāύāĻžāĻŦāϞ āĻāϰāĻžāϰ āĻāĻā§ āύāĻŋāĻā§āϰ āϞāĻžāĻāĻŦā§āϰā§āϰāĻŋāĻā§āϞā§āϰ āĻāĻŽā§āĻĒā§āϝāĻžāĻāĻŋāĻŦāĻŋāϞāĻŋāĻāĻŋ āĻāĻāĻŦāĻžāϰ āϝāĻžāĻāĻžāĻ āĻāϰ⧠āύāĻŋāύāĨ¤
āĻāĻā§ āĻāĻā§ āĻāĻ āĻāĻŽā§āĻĒā§āύā§āύā§āĻāĻā§āϞ⧠āĻŦāĻžāύāĻžāĻŦā§: Navbar, MovieCard, MovieGrid, MovieDetailsModal, Cart, Footer â āĻāĻŦāĻ āĻĒā§āϰāϤāĻŋāĻāĻž āĻŦāĻžāύāĻžāύā§āϰ āĻĒāϰ App.jsx-āĻ āĻā§āĻĄāĻŧāĻž āϞāĻžāĻāĻŋāϝāĻŧā§ āĻĒā§āĻ āĻ
ā§āϝāĻžāϏā§āĻŽā§āĻŦāϞ āĻāϰāĻŦāĨ¤
āϧāĻžāĻĒ ā§Ģ: Data āĻĢā§āϞā§āĻĄāĻžāϰ â āĻŽā§āĻāĻŋ āĻĄā§āĻāĻž āĻšāĻžāϰā§āĻĄāĻā§āĻĄ āϰāĻžāĻāĻž
API āĻāύā§āĻāĻŋāĻā§āϰā§āĻļāύā§āϰ āĻāĻā§ UI develop āĻ test āĻāϰāĻžāϰ āĻāύā§āϝ hardcoded mock data layer āĻŦāĻžāύāĻžāύ⧠āĻāĻāĻāĻž āĻāĻŽāύ āĻāϰ āϏā§āĻŽāĻžāϰā§āĻ āĻĒā§āϰā§āϝāĻžāĻāĻāĻŋāϏāĨ¤ āĻāĻŦāĻŋāώā§āϝāϤ⧠āĻāĻ array-āĻā§ āĻāĻāĻ shape āĻŽā§āύ⧠API response āĻĻāĻŋāϝāĻŧā§ āϰāĻŋāĻĒā§āϞā§āϏ āĻāϰāϞ⧠āĻāĻŽā§āĻĒā§āύā§āύā§āĻ āĻā§āĻĄā§ āĻāĻ āϞāĻžāĻāύāĻ āĻŦāĻĻāϞāĻžāϤ⧠āĻšāĻŦā§ āύāĻžāĨ¤
// src/data/movies.js
/**
* @typedef {Object} Movie
* @property {number} id
* @property {string} title
* @property {string} poster
* @property {number} rating
* @property {string[]} genres
* @property {number} price
*/
/** @type {Movie[]} */
export const movies = [
{
id: 1,
title: "āĻāύā§āĻāĻžāϰāϏā§āĻā§āϞāĻžāϰ",
poster: "/images/movies/interstellar.jpg",
rating: 8.7,
genres: ["Sci-Fi", "Drama"],
price: 120,
},
{
id: 2,
title: "āĻāύāϏā§āĻĒāĻļāύ",
poster: "/images/movies/inception.jpg",
rating: 8.8,
genres: ["Action", "Sci-Fi"],
price: 150,
},
];āĻāĻāĻžāύ⧠JSDoc @typedef āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻžāϝāĻŧ plain JavaScript āĻĒā§āϰāĻā§āĻā§āĻā§āĻ VS Code-āĻ IntelliSense āĻāϰ type-checking-āĻāϰ āϏā§āĻŦāĻŋāϧāĻž āĻĒāĻžāĻāϝāĻŧāĻž āϝāĻžāϝāĻŧ â āĻāϰ āĻĒāϰāĻŦāϰā§āϤā§āϤ⧠TypeScript-āĻ āĻŽāĻžāĻāĻā§āϰā§āĻ āĻāϰāĻžāĻ āϏāĻšāĻ āĻšāϝāĻŧā§ āϝāĻžāϝāĻŧāĨ¤
āĻĒā§āϰāĻžāĻāϏ āĻĢāϰāĻŽā§āϝāĻžāĻ āĻāϰāĻžāϰ āĻāύā§āϝ hardcoded ā§ŗ āϏā§āĻā§āϰāĻŋāĻ āĻā§āĻĄāĻŧāĻž āĻĻā§āĻāϝāĻŧāĻžāϰ āĻŦāĻĻāϞ⧠Intl.NumberFormat āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰā§āύ:
// src/lib/formatPrice.js
export function formatPrice(amount) {
return new Intl.NumberFormat("bn-BD", {
style: "currency",
currency: "BDT",
}).format(amount);
}āϧāĻžāĻĒ ā§Ŧ: CartContext āĻ useReducer āĻĻāĻŋāϝāĻŧā§ Cart āϏāĻŋāϏā§āĻā§āĻŽ
Step 2-āĻ āĻĒā§āϞā§āϝāĻžāύ āĻāϰāĻž Reducer Pattern āĻāĻāύ āĻŦāĻžāϏā§āϤāĻŦā§ āύāĻžāĻŽāĻžāĻŦā§āĨ¤ cartReducer-āĻā§ āĻāϞāĻžāĻĻāĻž āĻĢāĻžāĻāϞ⧠āϰāĻžāĻāĻŦ, āϝāĻžāϤ⧠logic āĻāϰ Context configuration āĻāϞāĻžāĻĻāĻž āĻĨāĻžāĻā§ (separation of concerns):
// src/context/cartReducer.js
export const initialCartState = { items: [] };
export function cartReducer(state, action) {
switch (action.type) {
case "ADD_TO_CART": {
const exists = state.items.some((item) => item.id === action.payload.id);
if (exists) return state; // duplicate āĻšāϞ⧠warning component āϞā§āĻā§āϞ⧠āĻĻā§āĻāĻžāĻŦ
return { items: [...state.items, action.payload] };
}
case "REMOVE_FROM_CART":
return {
items: state.items.filter((item) => item.id !== action.payload.id),
};
case "CLEAR_CART":
return { items: [] };
default:
return state;
}
}// src/context/CartContext.jsx
import { createContext, useContext, useReducer, useMemo } from "react";
import { cartReducer, initialCartState } from "./cartReducer";
const CartContext = createContext(null);
export function CartProvider({ children }) {
const [state, dispatch] = useReducer(cartReducer, initialCartState);
// Derived state â āĻŽā§āĻ āĻĻāĻžāĻŽ āĻ āĻāĻāĻā§āĻŽ āϏāĻāĻā§āϝāĻž āĻāϞāĻžāĻĻāĻž state āĻšāĻŋāϏā§āĻŦā§ āύāĻž āϰā§āĻā§ calculate āĻāϰāĻāĻŋ
const totalPrice = useMemo(
() => state.items.reduce((sum, item) => sum + item.price, 0),
[state.items],
);
const value = {
items: state.items,
totalPrice,
itemCount: state.items.length,
addToCart: (movie) => dispatch({ type: "ADD_TO_CART", payload: movie }),
removeFromCart: (id) =>
dispatch({ type: "REMOVE_FROM_CART", payload: { id } }),
clearCart: () => dispatch({ type: "CLEAR_CART" }),
isInCart: (id) => state.items.some((item) => item.id === id),
};
return <CartContext.Provider value={value}>{children}</CartContext.Provider>;
}
export function useCart() {
const context = useContext(CartContext);
if (!context) throw new Error("useCart must be used within a CartProvider");
return context;
}MovieCard-āĻ duplicate-add āĻšāϞ⧠āĻāϝāĻŧāĻžāϰā§āύāĻŋāĻ āĻĻā§āĻāĻžāύā§āϰ āĻāύā§āϝ isInCart āĻā§āĻ āĻāϰ⧠āĻāύā§āĻĄāĻŋāĻļāύāĻžāϞāĻŋ āĻŽā§āϏā§āĻ āĻĻā§āĻāĻžāĻŦā§:
// src/components/movies/MovieCard.jsx
import { ShoppingCart } from "lucide-react";
import { useCart } from "../../context/CartContext";
import { formatPrice } from "../../lib/formatPrice";
export function MovieCard({ movie }) {
const { addToCart, isInCart } = useCart();
const alreadyAdded = isInCart(movie.id);
function handleAddToCart() {
if (alreadyAdded) {
alert(`"${movie.title}" āĻāĻā§ āĻĨā§āĻā§āĻ āĻāĻžāϰā§āĻā§ āϝā§āĻā§āϤ āĻāĻā§āĨ¤`); // āĻĒā§āϰā§āĻĄāĻžāĻāĻļāύ⧠toast notification āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻž āĻāĻžāϞā§
return;
}
addToCart(movie);
}
return (
<div className="rounded-lg border border-secondary/20 p-4">
<img src={movie.poster} alt={movie.title} className="rounded-md" />
<h3 className="mt-2 font-display font-semibold">{movie.title}</h3>
<p className="text-sm text-secondary">â {movie.rating}</p>
<button
onClick={handleAddToCart}
className="mt-3 flex items-center gap-2 rounded-md bg-primary px-3 py-2 text-white"
>
<ShoppingCart size={16} />
{formatPrice(movie.price)}
</button>
</div>
);
}āϧāĻžāĻĒ ā§: MovieDetailsModal â āĻā§āϞā§āĻ āĻāĻĒ āĻļāĻ
āĻŽā§āĻāĻŋ āĻāĻžāϰā§āĻĄā§ āĻā§āϞāĻŋāĻ āĻāϰāϞ⧠āϝ⧠modal āĻā§āϞāĻŦā§, āϏā§āĻāĻžāĻā§ DOM hierarchy-āϤ⧠MovieCard-āĻāϰ āĻā§āϤāϰ⧠āύā§āϏā§āĻā§āĻĄ āύāĻž āϰā§āĻā§ createPortal āĻĻāĻŋāϝāĻŧā§ āϏāϰāĻžāϏāϰāĻŋ document.body-āĻāϰ āĻāĻžāĻāϞā§āĻĄ āĻšāĻŋāϏā§āĻŦā§ āϰā§āύā§āĻĄāĻžāϰ āĻāϰāĻžāĻ āĻŦā§āĻĻā§āϧāĻŋāĻŽāĻžāύā§āϰ āĻāĻžāĻ â āĻāϤ⧠overflow: hidden āĻŦāĻž z-index stacking context-āĻāύāĻŋāϤ āĻšā§āϝāĻžāĻĒāĻž āĻāĻĄāĻŧāĻžāύ⧠āϝāĻžāϝāĻŧ:
// src/components/movies/MovieDetailsModal.jsx
import { createPortal } from "react-dom";
import { useEffect } from "react";
import { X } from "lucide-react";
export function MovieDetailsModal({ movie, onClose }) {
// Escape āĻā§ āĻĻāĻŋāϝāĻŧā§ modal āĻŦāύā§āϧ āĻāϰāĻžāϰ accessibility support
useEffect(() => {
function handleKeyDown(e) {
if (e.key === "Escape") onClose();
}
window.addEventListener("keydown", handleKeyDown);
return () => window.removeEventListener("keydown", handleKeyDown);
}, [onClose]);
if (!movie) return null;
return createPortal(
<div
className="fixed inset-0 z-50 flex items-center justify-center bg-black/60"
onClick={onClose}
>
<div
className="relative max-w-lg rounded-lg bg-white p-6 dark:bg-zinc-900"
onClick={(e) => e.stopPropagation()}
>
<button onClick={onClose} className="absolute right-4 top-4">
<X size={20} />
</button>
<img src={movie.poster} alt={movie.title} className="rounded-md" />
<h2 className="mt-4 text-xl font-bold">{movie.title}</h2>
<p className="mt-2 text-sm">āĻāύāϰāĻž: {movie.genres.join(", ")}</p>
</div>
</div>,
document.body,
);
}selected movie-āĻāϰ state āϰāĻžāĻāĻŦ HomePage-āĻ â āϞā§āĻāĻžāϞ state āĻšāĻŋāϏā§āĻŦā§, āĻāĻžāϰāĻŖ āĻāĻāĻž āĻļā§āϧ⧠āĻāĻ āĻĒā§āĻā§āϰ modal-āĻāϰ āĻāύā§āϝāĻ āĻĻāϰāĻāĻžāϰ, āĻā§āϞā§āĻŦāĻžāϞ āĻāϰāĻžāϰ āĻĻāϰāĻāĻžāϰ āύā§āĻ:
// src/pages/HomePage.jsx
import { useState } from "react";
import { movies } from "../data/movies";
import { MovieCard } from "../components/movies/MovieCard";
import { MovieDetailsModal } from "../components/movies/MovieDetailsModal";
export function HomePage() {
const [selectedMovie, setSelectedMovie] = useState(null);
return (
<div className="container grid grid-cols-2 gap-4 md:grid-cols-4">
{movies.map((movie) => (
<div key={movie.id} onClick={() => setSelectedMovie(movie)}>
<MovieCard movie={movie} />
</div>
))}
<MovieDetailsModal
movie={selectedMovie}
onClose={() => setSelectedMovie(null)}
/>
</div>
);
}āĻŦā§āύāĻžāϏ â URL-driven Modal (React Router v8): Deep-linking āϏāĻžāĻĒā§āϰā§āĻ āĻāĻžāĻāϞ⧠/movies/:id āϰāĻžāĻāĻā§ āĻŽāĻĄāĻžāϞ-āĻāĻŋāϤā§āϤāĻŋāĻ āĻĄāĻŋāĻā§āĻāϞāϏ āĻĒā§āĻ āĻŽā§āϝāĻžāĻĒ āĻāϰāĻž āϝāĻžāϝāĻŧ:
npm install react-routerimport {
BrowserRouter,
Routes,
Route,
useParams,
useNavigate,
} from "react-router";
function MovieDetailsRoute() {
const { id } = useParams();
const navigate = useNavigate();
const movie = movies.find((m) => m.id === Number(id));
return <MovieDetailsModal movie={movie} onClose={() => navigate(-1)} />;
}āϞāĻā§āώ āĻāϰā§āύ â āĻāĻāύ āĻĨā§āĻā§ āĻļā§āϧ⧠react-router āĻĒā§āϝāĻžāĻā§āĻ āĻāĻŽā§āĻĒā§āϰā§āĻ āĻāϰāϞā§āĻ āĻšāϝāĻŧāĨ¤ react-router-dom āĻāĻāύ react-router-āĻāϰāĻ āĻāĻāĻāĻž re-export āĻŽāĻžāϤā§āϰāĨ¤
āϧāĻžāĻĒ ā§Ž: āϞāĻžāĻāĻ āĻ āĻĢ, āĻĄāĻžāϰā§āĻ āĻ āύ â Theme Switch đ
āĻĨāĻŋāĻŽ āϏā§āĻāĻāĻŋāĻāϝāĻŧā§āϰ āĻāύā§āϝ āĻāϞāĻžāĻĻāĻž āĻāĻāĻāĻž ThemeContext āĻŦāĻžāύāĻžāĻŦā§, āϝāĻž āĻĒā§āϰ⧠āĻ
ā§āϝāĻžāĻĒā§ theme state āĻļā§āϝāĻŧāĻžāϰ āĻāϰāĻŦā§ āĻāĻŦāĻ localStorage-āĻ persist āĻāϰāĻŦā§ â āϝāĻžāϤ⧠āĻĒā§āĻ āϰāĻŋāĻĢā§āϰā§āĻļā§āϰ āĻĒāϰāĻ āĻāĻāĻāĻžāϰā§āϰ āĻĒāĻāύā§āĻĻ āĻŽāύ⧠āĻĨāĻžāĻā§āĨ¤
// src/context/ThemeContext.jsx
import { createContext, useContext, useEffect, useState } from "react";
const ThemeContext = createContext(null);
export function ThemeProvider({ children }) {
const [theme, setTheme] = useState(
() => localStorage.getItem("theme") || "light",
);
useEffect(() => {
const root = document.documentElement;
root.classList.toggle("dark", theme === "dark");
localStorage.setItem("theme", theme);
}, [theme]);
const toggleTheme = () =>
setTheme((prev) => (prev === "light" ? "dark" : "light"));
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
}
export function useTheme() {
const context = useContext(ThemeContext);
if (!context) {
throw new Error("useTheme must be used within a ThemeProvider");
}
return context;
}main.jsx-āĻ āĻĒā§āϰ⧠āĻ
ā§āϝāĻžāĻĒāĻā§ ThemeProvider āĻ CartProvider āĻĻāĻŋāϝāĻŧā§ wrap āĻāϰ⧠āĻĻā§āĻŦ (Provider-āĻāϰ nesting order āĻā§āĻāύāĻŋāĻā§āϝāĻžāϞāĻŋ āĻŽā§āϝāĻžāĻāĻžāϰ āĻāϰ⧠āύāĻž, āϤāĻŦā§ readability-āϰ āĻāύā§āϝ āϏāĻŦāĻā§āϝāĻŧā§ āĻā§āϞā§āĻŦāĻžāϞ context āĻŦāĻžāĻāϰ⧠āϰāĻžāĻāĻžāĻ āĻāĻžāϞā§):
import { ThemeProvider } from "./context/ThemeContext";
import { CartProvider } from "./context/CartContext";
createRoot(document.getElementById("root")).render(
<ThemeProvider>
<CartProvider>
<App />
</CartProvider>
</ThemeProvider>,
);Tailwind v4-āĻāϰ dark variant āĻāĻŽāϰāĻž āĻāĻā§āĻ āϧāĻžāĻĒ ā§¨-āĻ @custom-variant dark (&:where(.dark, .dark *)); āĻĻāĻŋāϝāĻŧā§ āĻāύāĻĢāĻŋāĻāĻžāϰ āĻāϰ⧠āϰā§āĻā§āĻāĻŋāĨ¤ āĻĢāϞ⧠dark:bg-black dark:text-white-āĻāϰ āĻŽāϤ⧠āĻā§āϞāĻžāϏāĻā§āϞ⧠<html> āĻā§āϝāĻžāĻā§ .dark āĻā§āϞāĻžāϏ āĻĨāĻžāĻāϞā§āĻ āĻ
ā§āϝāĻžāĻā§āĻāĻŋāĻ āĻšāϝāĻŧā§ āϝāĻžāĻŦā§ â āϝā§āĻāĻž āĻāĻŽāĻžāĻĻā§āϰ ThemeContext āĻāĻāϞ āĻāϰ⧠āĻĻāĻŋāĻā§āĻā§āĨ¤
Flash of Unstyled Theme (FOUC) āĻ ā§āĻāĻžāύ: React hydrate āĻšāĻāϝāĻŧāĻžāϰ āĻāĻā§āĻ āϝā§āύ āϏāĻ āĻŋāĻ āĻĨāĻŋāĻŽ apply āĻšāϝāĻŧā§ āϝāĻžāϝāĻŧ, āϤāĻžāϰ āĻāύā§āϝ index.html-āĻ <body>-āĻāϰ āĻāĻā§ āĻāĻāĻāĻž āĻā§āĻā§āĻ blocking script āĻŦāϏāĻŋāϝāĻŧā§ āĻĻāĻŋāύ:
<script>
(function () {
const theme = localStorage.getItem("theme") || "light";
document.documentElement.classList.toggle("dark", theme === "dark");
})();
</script>āĻĨāĻŋāĻŽ āϏā§āĻāĻāĻžāϰ āϏā§āĻāĻžāĻāϞā§āϰ āϰā§āĻĢāĻžāϰā§āύā§āϏ āĻā§āϞāĻžāϏ â styles.css-āĻ āϝā§āĻ āĻāϰāϤ⧠āĻšāĻŦā§:
āϧāĻžāĻĒ ā§¯: āĻā§āĻĄ āĻā§āϝāĻŧāĻžāϞāĻŋāĻāĻŋ â āĻļā§āώ āĻĒāĻžāϞāĻŋāĻļ
Vite-āĻāϰ React āĻā§āĻŽāĻĒā§āϞā§āĻā§ āĻĄāĻŋāĻĢāϞā§āĻ ESLint flat config (eslint.config.js) āĻāĻā§ āĻĨā§āĻā§āĻ āĻĨāĻžāĻā§, āϝāĻž React Hooks rules āĻāϰ Fast Refresh āĻāύāĻā§āύāĻļāύ āĻāύāĻĢā§āϰā§āϏ āĻāϰā§āĨ¤ āϏāĻžāĻĨā§ Prettier āϝā§āĻ āĻāϰ⧠āĻĻāĻŋāϞ⧠āĻā§āĻĄ āĻĢāϰāĻŽā§āϝāĻžāĻāĻŋāĻ āĻāύāϏāĻŋāϏā§āĻā§āύā§āĻ āĻĨāĻžāĻā§:
npm install -D prettier eslint-config-prettierāĻāĻŋāĻŽā§ āĻāĻžāĻ āĻāϰāϞ⧠commit-āĻāϰ āĻāĻā§ lint/format āύāĻŋāĻļā§āĻāĻŋāϤ āĻāϰāϤ⧠husky + lint-staged āϏā§āĻāĻāĻĒ āĻāϰ⧠āύāĻŋāϤ⧠āĻĒāĻžāϰā§āύ â āĻāϤ⧠inconsistent āĻā§āĻĄ āĻŽā§āĻāύ āĻŦā§āϰāĻžāĻā§āĻā§ āĻĸā§āĻāϤ⧠āĻĒāĻžāϰāĻŦā§ āύāĻžāĨ¤
đŦ āĻāĻžāĻ! â āĻĒāϰā§āϰ āϧāĻžāĻĒā§ āϝāĻžāĻāϝāĻŧāĻžāϰ āĻāĻā§ āĻā§āĻāϞāĻŋāϏā§āĻ
- Vite + React 19.2 āĻĒā§āϰāĻā§āĻā§āĻ āϰāĻžāύ āĻšāĻā§āĻā§, HMR āĻāĻžāĻ āĻāϰāĻā§āĨ¤
- Tailwind CSS v4
@themeāĻāύāĻĢāĻŋāĻāϏāĻš āĻāύā§āϏāĻāϞ āĻāϰāĻž āĻšāϝāĻŧā§āĻā§; āĻāĻžāϏā§āĻāĻŽ āĻāĻžāϞāĻžāϰ āĻā§āĻā§āύ āĻ@custom-variant darkāĻā§āϰāĻŋāĻĢāĻžāĻ āĻāϰāĻž āĻšāϝāĻŧā§āĻā§āĨ¤ - HTML template-āĻāϰ āϏāĻŦ āĻŽāĻžāϰā§āĻāĻāĻĒ JSX āϏāĻŋāύāĻā§āϝāĻžāĻā§āϏ āĻ āύā§āϝāĻžāϝāĻŧā§ āϰā§āĻĒāĻžāύā§āϤāϰāĻŋāϤ āĻšāϝāĻŧā§āĻā§, assets āĻ āĻāĻāĻāύ āĻŽāĻžāĻāĻā§āϰā§āĻ āĻšāϝāĻŧā§āĻā§āĨ¤
- āĻĢā§āϞā§āĻĄāĻžāϰ āĻāϰā§āĻāĻŋāĻā§āĻāĻāĻžāϰ āĻ
āύā§āϝāĻžāϝāĻŧā§ āĻāĻŽā§āĻĒā§āύā§āύā§āĻāĻā§āϞ⧠(
Navbar,MovieCard,MovieGrid,FooterāĻāϤā§āϝāĻžāĻĻāĻŋ) āϤā§āϰāĻŋ āĻ composed āĻšāϝāĻŧā§āĻā§āĨ¤ -
src/data/movies.js-āĻ mock āĻĄā§āĻāĻž āϤā§āϰāĻŋ āĻ āĻāĻŽā§āĻĒā§āύā§āύā§āĻā§ wire āĻāϰāĻž āĻšāϝāĻŧā§āĻā§āĨ¤ -
CartContext+cartReducerāĻĻāĻŋāϝāĻŧā§ Add/Remove/Duplicate-warning āĻĢāĻŋāĻāĻžāϰ āĻāĻžāĻ āĻāϰāĻā§āĨ¤ -
MovieDetailsModalcreatePortalāĻĻāĻŋāϝāĻŧā§ āĻāĻžāĻ āĻāϰāĻā§, Escape āĻā§ āĻĻāĻŋāϝāĻŧā§ āĻŦāύā§āϧ āĻšāĻā§āĻā§āĨ¤ - Theme Context āĻĻāĻŋāϝāĻŧā§ Light/Dark mode āĻāĻāϞ āĻāĻžāĻ āĻāϰāĻā§, āϰāĻŋāĻĢā§āϰā§āĻļā§āϰ āĻĒāϰāĻ persist āĻāϰāĻā§, FOUC āύā§āĻāĨ¤
- ESLint/Prettier āϏā§āĻāĻāĻĒ āĻāϰāĻž āĻšāϝāĻŧā§āĻā§āĨ¤
āϏāĻŦ āĻŦāĻā§āϏ⧠āĻāĻŋāĻ āĻĒāĻĄāĻŧāϞ⧠â āĻāĻžāĻ, āĻĒā§āϰāĻŋāύā§āĻ! đĨ āĻāĻĒāύāĻžāϰ Movie Portal-āĻāϰ Act 1 āĻļā§āώāĨ¤ āĻĒāϰā§āϰ āĻĒāϰā§āĻŦā§ āĻāĻŽāϰāĻž āϏāĻžāϰā§āĻ, āĻĢāĻŋāϞā§āĻāĻžāϰ āĻāϰ āϰāĻŋāϝāĻŧā§āϞ API āύāĻŋāϝāĻŧā§ āĻāĻĨāĻž āĻŦāϞāĻŦāĨ¤