# Preparation - [ ] Watch https://www.youtube.com/watch?v=SqcY0GlETPk&ab_channel=ProgrammingwithMosh # CORS (Backend Repository) - [ ] open `program.cs` and add the following lines ```c# builder.Services.AddCors(options => { options.AddPolicy("Frontend", policy => { policy.WithOrigins("http://localhost:5173") .AllowAnyHeader() .AllowAnyMethod(); }); }); ... app.UseCors("Frontend"); ``` # **Important Note Before Starting** ## From now on, this session will be focused on the **frontend repository** ## If you have already created a the frontend project, with the deprecated command(create-react-app), you need to first delete all that, commit the changes, and then create the project using the next instruction # Branching - [ ] Create the develop branch - [ ] Create the feature/project-setup branch based on develop # Creating a project (using Vite) ``` npm create vite@latest alibabaclone-frontend --template react-ts ``` # React Folder Structure - [ ] Create the folders as shown in the picture below ![[Pasted image 20250427154917.png]] - [ ] move `App.tsx` and `App.css` to 'shared/layout/' - [ ] adjust the dependencies in these files and `index.html` # Installing packages - [ ] run this command to install these packages: `uuid`, `react-router-dom`, and `axios` ```bash npm install uuid react-router-dom axios ``` - [ ] run this command to install redux ```bash npm install @reduxjs/toolkit react-redux ``` # CSS TAILWIND ## **Important Note About CSS** There are different ways to handle `CSS` styling when creating components. You can choose any approach you prefer: 1. **Plain CSS** - Write regular `.css` files and import them into your components. 2. **CSS Modules** - Create component-specific `.module.css` files to automatically scope styles. 3. **TailwindCSS** - A utility-first CSS framework where you apply classes directly in your HTML/JSX. 4. **Sass / SCSS** - An extension of CSS with variables, nesting, and more features. Can be used alone or with modules. 5. **PostCSS** - A tool for transforming CSS with JavaScript plugins (often used behind the scenes). 6. **Framework-Specific UI Libraries** (which come with their own styles) - Example: Material-UI (MUI), Ant Design, Chakra UI, etc. - These often include ready-made components with built-in styling. - [ ] install the css/component library of your choice ### For tailwind, use the link below (skip the first step) Tailwind https://ui.shadcn.com/docs/installation/vite # Merge - [ ] Create a PR and merge the current branch with develop # Branching - [ ] Create the feature/transportation-search branch based on develop # Creating Models - [ ] Create models for the DTOs that are used to convey data between backend and frontend 📂 Suggested Folder: shared/models/[relatedFolder] Create a `[dtoName].ts` in the related folder, and define the model ## Example: ```ts export interface TransportationSearchRequest{     vehicleTypeId ?: number;     fromCityId ?: number;     toCityId ?: number;     startDate ?: Date | null;     endDate ?: Date | null; } ``` # Handling API Calls - [ ] Create `agent.ts` to handle API calls using axios 📂 Suggested Folder: shared/api/ - [ ] Adjust the `baseURL` to address your web API port ```ts import axios, { AxiosResponse } from 'axios'; import { TransportationSearchRequest } from '../models/transportation/transportationSearchRequest'; import { TransportationSearchResult } from '../models/transportation/transportationSearchResult'; import { City } from '../models/location/city'; axios.defaults.baseURL = 'https://localhost:[REPLACE THIS WITH YOUR BACKEND WEB API PORT]/api'; const responseBody = (response: AxiosResponse) => response.data; const request = {     get: (url: string) => axios.get(url).then(responseBody),     post: (url: string, body: {}) => axios.post(url, body).then(responseBody),     put: (url: string, body: {}) => axios.put(url, body).then(responseBody),     delete: (url: string) => axios.delete(url).then(responseBody) } const TransportationSearch = {     search: (data: TransportationSearchRequest) => request.post('/transportation/search', data), } const Cities = {     list: () => request.get('/city'), } const agent = {     TransportationSearch,     Cities } export default agent; ``` # Creating `CityDropdown` Component 📂 Suggested Folder: shared/api/ - [ ] Create components for the parts of the UI you need ```ts import agent from "@/shared/api/agent"; import { City } from "@/shared/models/location/city"; import { useEffect, useState } from "react"; const CityDropdown = () => {   const [cities, setCities] = useState([]);   const [selectedCity, setSelectedCity] = useState();   useEffect(() => {     agent.Cities.list()       .then(setCities)       .catch((err) => console.error("error loading cities", err));   }, []);   return (       ); }; export default CityDropdown; ``` ## **See the analysis of `CityDropdown` component code in the additional info** # Creating `transportationCard` Component ```ts import { TransportationSearchResult } from "@/shared/models/transportation/transportationSearchResult"; import React from "react"; interface Props {   transportation: TransportationSearchResult; } const TransportationCard: React.FC = ({ transportation }) => {   return (    
      {/* Price and Select Button */}      
       
          {transportation.price} Toman        
             
      {/* Trip Info */}      
       
          {transportation.companyTitle}        
       
         
{transportation.fromCityTitle}
                   
{transportation.toCityTitle}
       
       
          {new Date(transportation.startDateTime).toLocaleDateString("en", {             hour: "2-digit",             minute: "2-digit",           })}        
     
      {/* Company Logo or Placeholder */}      
        company      
   
  ); }; export default TransportationCard; ``` # Creating `transportationSearchForm` Component See the code from: https://github.com/MehrdadShirvani/AlibabaClone-Frontend/tree/develop/alibabaclone-frontend/src/features/transportation # Additional Notes: ## What is vite ## What is CORS? ### CORS (Cross-Origin Resource Sharing) **What it is:** CORS is a browser security feature that blocks requests to a different domain unless explicitly allowed by the server. ### 🔐 What is CORS **really** for? CORS is **not** about protecting the backend server. It’s about **protecting users** from **malicious websites** using their browser as a weapon. --- ### 🧠 Imagine this attack: You’re logged into your **bank** in one browser tab (`bank.com`). Now, you visit a shady website in another tab (`evil.com`). That site has JavaScript that tries to send this: ```js fetch('https://bank.com/api/transfer?amount=5000&to=hacker', { credentials: 'include' // it sends your bank cookies! }); ``` ➡️ If the browser allowed this freely, the request would go through **using your login session**, and you’d lose money. --- ### 💥 Enter CORS So the browser says: > “Hold on. This JavaScript is from `evil.com`, and it’s trying to talk to `bank.com`. I won’t let that happen **unless `bank.com` says it’s okay**.” That’s why the **backend server** must respond with something like: ```http Access-Control-Allow-Origin: https://mytrusteddomain.com ``` Only then will the browser say, “Okay, go ahead.” --- ### So the purpose of CORS is: ✅ To **restrict browsers** from sending or accepting responses from **cross-origin** sources ❌ Not to protect the backend ❌ Not to restrict Postman, curl, servers, or mobile apps --- ### 🔄 In Dev Work (like your React + API case): - You’re running React at `http://localhost:5173` - You’re running ASP.NET Core API at `https://localhost:7001` - The browser sees this as two **different origins** → blocks the request unless CORS is enabled on the API. --- ### 🧪 Why Postman works: - Postman isn’t a browser - Postman doesn’t care about same-origin policy - Postman just sends requests like your backend would --- ### ✅ Conclusion: - **CORS is a browser feature to protect users** - **It restricts frontend JavaScript from calling other domains unless explicitly allowed** - **You must configure your server to say “Yes, I allow your frontend to talk to me”** ## Feature-based Folder Structure ## Explanation of the `agent.ts` ## React.FC ### In your code: ```tsx const TransportationCard: React.FC = ({ transportation }) => { ... } ``` You're using `React.FC`. ✅ `FC` stands for **Function Component**. --- ### So what is `React.FC` exactly? - `React.FC` (or `React.FunctionComponent`) is a **TypeScript type** that you can use to type your functional React components. - It **tells TypeScript** that: - This component is a function - It **receives props** (in your case, `Props`) - It **returns JSX** (it returns something React can render) --- ### Why use it? Here’s what you get when you use `React.FC`: 1. ✅ **Prop typing** — You get auto-complete and error checking for props. 2. ✅ **Children** are automatically included. (More on this below.) 3. ✅ **Cleaner code** because TypeScript understands the shape of the component. --- ### Without `React.FC` You could just write: ```tsx const TransportationCard = ({ transportation }: Props) => { ... } ``` and it would work! But you lose some "extra typing safety" like automatic `children` typing. --- ### Small Detail: `children` When you use `React.FC`, **TypeScript automatically** allows your component to accept `children` too — even if you didn’t define it in your `Props`. For example: ```tsx

Hello

// This would be valid automatically
``` Because `children` is **always** part of a `React.FC`. 👉 If you **don't** use `React.FC`, and you want to accept `children`, you have to **manually** add it to your props. --- ### Some developers today... **Some people** (even in big companies) prefer **NOT** to use `React.FC` anymore because: - It **forces children** even when you don’t want children. - It's **a little bit redundant** — you can already just type props without it. > So in modern codebases, **both styles are OK** — it’s just a preference. --- ### Quick Summary: |Using `React.FC`|Not using `React.FC`| |:--|:--| |Good for simple, typed functional components|Good if you want full manual control over props| |Auto-includes `children` prop|You must manually add `children` if needed| |Easy and quick|More customizable| --- --- Would you like me to also show a real quick **example side-by-side** (with and without `React.FC`) so you can see the difference even more clearly? 🚀 (It's super fast but very helpful!) ## `CityDropdown` Component: ### 1. **State Variables** ```tsx const [cities, setCities] = useState([]); const [selectedCity, setSelectedCity] = useState(); ``` - `cities`: holds the list of cities retrieved from the backend (starts empty `[]`). - `selectedCity`: holds the currently selected city’s ID (`number`) or `undefined` if nothing is selected yet. --- ### 2. **Fetching Cities on Mount** ```tsx useEffect(() => { agent.Cities.list() .then(setCities) .catch((err) => console.error("error loading cities", err)); }, []); ``` - When the component **mounts** (`[]` dependency array = run once), it calls `agent.Cities.list()`. - `agent.Cities.list()` presumably returns a promise that resolves to an array of `City` objects. - On success → `setCities` updates the `cities` state. - On failure → logs an error to the console. --- ### 3. **Rendering the Dropdown** ```tsx ``` - Renders a `` dropdown fills up! --- #### 3. ✏️ Handle input changes ```tsx const handleChange = (e: React.ChangeEvent) => { ... } ``` Whenever a user types/selects: - You detect **which field** (`name`) and **what value** (`value`) they changed - Update the `form` state accordingly: - `fromCityId` and `toCityId` are converted to numbers (`parseInt`) - `startDate` and `endDate` allow null - Other fields (if any) are copied directly --- #### 4. 🔍 Handle Search button ```tsx const handleSearch = () => { ... } ``` When the user clicks **Search**: - Set `loading` to `true` - Call the backend API `agent.TransportationSearch.search(form)` - When the result comes back: - Save it into `searchResults` - If error: log it - Finally, set `loading` to `false` again --- #### 5. 🖥️ Return (render) JSX You build a UI: - **Vehicle Types** (Bus, Train, Airplane) selectable with a click → sets `vehicleTypeId` - **From City** and **To City** dropdowns - **Start and End Date** inputs - **Search Button** to trigger the search - **Result area** that shows: - If loading: "Loading..." - If no results: "No results found" - If results: List of `TransportationCard` components for each found item. ---