refactor: clean session06 notes

This commit is contained in:
2025-07-18 12:51:53 +03:30
parent 26bee3ff72
commit 750b997713
2 changed files with 134 additions and 161 deletions
@@ -0,0 +1,92 @@
## `SearchResultsPage`
This page is responsible for:
1. **Reading route parameters and query strings from the URL**
2. **Sending those values as a form to the backend**
3. **Showing the result (or loading/error message)**
---
### ✅ 1. **Route Parameters**
When you define this route in `App.jsx`:
```jsx
<Route path="/:vehicleId/:fromCityId/:toCityId" element={<SearchResultsPage />} />
```
It means the URL will look like:
```
/1/21/45
```
Those values are extracted using:
```js
const { vehicleId, fromCityId, toCityId } = useParams();
```
🔹 `useParams()` comes from React Router and gives you access to the dynamic parts of the URL.
---
### ✅ 2. **Query String Parameters**
Suppose your full URL is:
```
/1/21/45?departing=2025-06-01&arriving=2025-06-10
```
These extra values after the `?` are **query string parameters**. They're accessed using:
```js
const query = useQuery(); // Custom helper
const departing = query.get("departing");
const arriving = query.get("arriving");
```
The helper `useQuery()` is:
```js
function useQuery() {
return new URLSearchParams(useLocation().search);
}
```
This uses React Router's `useLocation()` to access the full URL, and then parses the query string.
---
### ✅ 3. **Parsing and Converting Values**
React Router gives you everything as strings. So:
```js
const vehicleTypeId = vehicleId ? parseInt(vehicleId, 10) : 1;
const fromId = fromCityId ? parseInt(fromCityId, 10) : undefined;
const toId = toCityId ? parseInt(toCityId, 10) : undefined;
```
This ensures you have **numbers**, not strings, when building your form object.
---
### ✅ 4. **Building the Search Form and Fetching Data**
Now all data is combined into one `form` object:
```js
const form = {
vehicleTypeId,
fromCityId: fromId,
toCityId: toId,
startDate: departing || null,
endDate: arriving || null,
};
```
Then it sends that to the backend:
```js
agent.TransportationSearch.search(form)
.then(setResults)
.catch(err => console.error(err))
.finally(() => setLoading(false));
```
@@ -1,9 +1,11 @@
# Branching # 🛠️ Task Checklist
## 🚧Branching
- [ ]  Create the feature/navbar branch based on develop - [ ]  Create the feature/navbar branch based on develop
# Adding a Navbar ## Adding a Navbar
## 🔹 What Is a Navbar? ### 🔹 What Is a Navbar?
- A **navigation bar (navbar)** is a UI element typically placed at the **top** or **side** of a web app. - A **navigation bar (navbar)** is a UI element typically placed at the **top** or **side** of a web app.
- [ ] Use a `<nav>` with `flex`, `justify-between`, `items-center`. - [ ] Use a `<nav>` with `flex`, `justify-between`, `items-center`.
@@ -11,54 +13,41 @@
use this as a reference: [link](https://github.com/MehrdadShirvani/AlibabaClone-Frontend/tree/develop/alibabaclone-frontend/src/shared/components) use this as a reference: [link](https://github.com/MehrdadShirvani/AlibabaClone-Frontend/tree/develop/alibabaclone-frontend/src/shared/components)
📂 Suggested Folder for navbar component: `src/shared/components/Navbar`
📂 Suggested Folder for images: `public/images/`
link to project: ## 🚧Merge
📂 Suggested Folder for navbar component: src/shared/components/Navbar
📂 Suggested Folder for images: public/images/
# Merge
- [ ] Create a PR and merge the current branch with develop - [ ] Create a PR and merge the current branch with develop
# Branching ## 🚧Branching
- [ ]  Create the feature/routing branch based on develop - [ ]  Create the feature/routing branch based on develop
# Modifying Project From Single Component to Routed Pages ## Converting Search Functionality From Single Component to Routed Pages
Originally, transportation search logic and UI may have all been inside one component — which quickly becomes messy and hard to manage as your app grows.
Originally, your transportation search logic and UI may have all been inside one component — which quickly becomes messy and hard to manage as your app grows.
Now weve **split the logic into two proper pages**: Now weve **split the logic into two proper pages**:
### ✅ `SearchPage.jsx` ### ✅ `SearchPage.jsx`
- Responsible only for showing the **search form**. - Responsible only for showing the **search form**.
- Clean and minimal. - Clean and minimal.
- Uses the reusable `TransportationSearchForm` component. - Uses the reusable `TransportationSearchForm` component.
- use this as a reference: [link](https://github.com/MehrdadShirvani/AlibabaClone-Frontend/tree/develop/alibabaclone-frontend/src/features/transportation/pages) - Use this as a reference: [link](https://github.com/MehrdadShirvani/AlibabaClone-Frontend/tree/develop/alibabaclone-frontend/src/features/transportation/pages)
### ✅ `SearchResultsPage.jsx` ### ✅ `SearchResultsPage.jsx`
- Responsible for **fetching and showing results**. - Responsible for **fetching and showing results**.
- Reads route parameters and query strings. - Reads route parameters and query strings.
- Calls the backend using `agent`. - Calls the backend using `agent`.
- Shows a loading state, handles empty results, and renders cards. - Shows a loading state, handles empty results, and renders cards.
- use this as a reference: [link](https://github.com/MehrdadShirvani/AlibabaClone-Frontend/tree/develop/alibabaclone-frontend/src/features/transportation/pages) - Use this as a reference: [link](https://github.com/MehrdadShirvani/AlibabaClone-Frontend/tree/develop/alibabaclone-frontend/src/features/transportation/pages)
This separation improves: This separation improves:
- Routing and navigation - Routing and navigation
- Code readability and maintainability - Code readability and maintainability
- Reusability of components like the search form and result cards - Reusability of components like the search form and result cards
--- ---
### **Create Pages into a Pages Folder**
## **Create Pages into a Pages Folder**
📂 Suggested Folder for navbar component 📂 Suggested Folder for navbar component
Inside your `features/transportation` folder: Inside your `features/transportation` folder:
@@ -71,10 +60,7 @@ components/
├── TransportationCard.jsx ├── TransportationCard.jsx
``` ```
### 2. **Create `SearchPage`** - [ ] Create `SearchPage`
Use:
```jsx ```jsx
import TransportationSearchForm from "@/features/transportation/transportationSearchForm"; import TransportationSearchForm from "@/features/transportation/transportationSearchForm";
@@ -88,11 +74,9 @@ const SearchPage = () => {
export default SearchPage; export default SearchPage;
``` ```
> Keep the form clean and layout minimal.
Keep the form clean and layout minimal. - [ ] Create `SearchResultsPage`
### 3. **Create `SearchResultsPage`**
- Use `useParams()` for URL parameters (`vehicleId`, `fromCityId`, `toCityId`) - Use `useParams()` for URL parameters (`vehicleId`, `fromCityId`, `toCityId`)
- Use `useLocation()` and `URLSearchParams` to read query strings (`departing`, `arriving`) - Use `useLocation()` and `URLSearchParams` to read query strings (`departing`, `arriving`)
- Fetch data from backend using a shared `agent` - Fetch data from backend using a shared `agent`
@@ -170,110 +154,15 @@ const SearchResultsPage = () => {
export default SearchResultsPage; export default SearchResultsPage;
``` ```
#### 🔍 SearchResultsPage Understanding Parameters and Arguments #### 🔍 `SearchResultsPage` Understanding Parameters and Arguments
- [ ] Check out [[Session06 Additional Info]]
This page is responsible for:
1. **Reading route parameters and query strings from the URL**
2. **Sending those values as a form to the backend**
3. **Showing the result (or loading/error message)**
--- ---
### Modifying `TransportationSearchForm`:
> Use this as a reference: [link](https://github.com/MehrdadShirvani/AlibabaClone-Frontend/tree/develop/alibabaclone-frontend/src/features/transportation)
##### ✅ 1. **Route Parameters** - [ ] Remove Search Result fetching from inside the component
- [ ] Update `handleSearch` to Navigate with Parameters
When you define this route in `App.jsx`:
```jsx
<Route path="/:vehicleId/:fromCityId/:toCityId" element={<SearchResultsPage />} />
```
It means the URL will look like:
```
/1/21/45
```
Those values are extracted using:
```js
const { vehicleId, fromCityId, toCityId } = useParams();
```
🔹 `useParams()` comes from React Router and gives you access to the dynamic parts of the URL.
---
##### ✅ 2. **Query String Parameters**
Suppose your full URL is:
```
/1/21/45?departing=2025-06-01&arriving=2025-06-10
```
These extra values after the `?` are **query string parameters**. They're accessed using:
```js
const query = useQuery(); // Custom helper
const departing = query.get("departing");
const arriving = query.get("arriving");
```
The helper `useQuery()` is:
```js
function useQuery() {
return new URLSearchParams(useLocation().search);
}
```
This uses React Router's `useLocation()` to access the full URL, and then parses the query string.
---
##### ✅ 3. **Parsing and Converting Values**
React Router gives you everything as strings. So:
```js
const vehicleTypeId = vehicleId ? parseInt(vehicleId, 10) : 1;
const fromId = fromCityId ? parseInt(fromCityId, 10) : undefined;
const toId = toCityId ? parseInt(toCityId, 10) : undefined;
```
This ensures you have **numbers**, not strings, when building your form object.
---
##### ✅ 4. **Building the Search Form and Fetching Data**
Now all data is combined into one `form` object:
```js
const form = {
vehicleTypeId,
fromCityId: fromId,
toCityId: toId,
startDate: departing || null,
endDate: arriving || null,
};
```
Then it sends that to the backend:
```js
agent.TransportationSearch.search(form)
.then(setResults)
.catch(err => console.error(err))
.finally(() => setLoading(false));
```
---
### 4. **Modify `TransportationSearchForm`:**
use this as a reference: [link](https://github.com/MehrdadShirvani/AlibabaClone-Frontend/tree/develop/alibabaclone-frontend/src/features/transportation)
#### 1. **Removed Search Result Fetching from Inside the Component**
#### 2. **Updated `handleSearch` to Navigate with Parameters**
```tsx ```tsx
const handleSearch = () => { const handleSearch = () => {
@@ -299,35 +188,24 @@ const handleSearch = () => {
``` ```
**Changes made:** **Changes made:**
- It **checks form validity** first. - It **checks form validity** first.
- Then it builds a **URL using `URLSearchParams`** for `departing` and `arriving` dates. - Then it builds a **URL using `URLSearchParams`** for `departing` and `arriving` dates.
- Then it calls `navigate(...)` to go to a **route like**: - Then it calls `navigate(...)` to go to a **route like**:
``` ```
/1/2/3?departing=2025-06-15T00%3A00%3A00.000Z&arriving=2025-06-18T00%3A00%3A00.000Z /1/2/3?departing=2025-06-15T00%3A00%3A00.000Z&arriving=2025-06-18T00%3A00%3A00.000Z
``` ```
> That route (`/vehicleTypeId/fromCityId/toCityId`) will be handled by your `SearchResultPage` via `react-router`. > That route (`/vehicleTypeId/fromCityId/toCityId`) will be handled by your `SearchResultPage` via `react-router`.
--- ---
#### 3. **Used `useNavigate` from `react-router-dom`** - [ ] Used `useNavigate` from `react-router-dom`
```tsx ```tsx
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
``` ```
- [ ] Removed Result Display Section
#### 4. **Removed Result Display Section**
## Add Routing
# Add Routing
- [ ] Change `App.tsx` as the following: - [ ] Change `App.tsx` as the following:
```tsx ```tsx
import Navbar from "@/shared/components/navbar"; import Navbar from "@/shared/components/navbar";
@@ -359,38 +237,32 @@ function App() {
export default App; export default App;
``` ```
### Explanation of `App.jsx` ### Explanation of `App.jsx`
#### 🔁 `Router` & `Routes`: #### 🔁 `Router` & `Routes`:
- Wraps the entire app in `<Router>` so that React Router can manage navigation. - Wraps the entire app in `<Router>` so that React Router can manage navigation.
- `<Routes>` contains all the individual page routes. - `<Routes>` contains all the individual page routes.
--- ---
#### 📌 Routes: #### 📌 Routes:
- `/`: Loads `SearchPage`. This is your home/search form. - `/`: Loads `SearchPage`. This is your home/search form.
- `/:vehicleId/:fromCityId/:toCityId`: Loads `SearchResultsPage`. This URL carries parameters to display results based on user input. - `/:vehicleId/:fromCityId/:toCityId`: Loads `SearchResultsPage`. This URL carries parameters to display results based on user input.
--- ---
#### 🎯 Navbar Placement: #### 🎯 Navbar Placement:
- Placed **outside** `<Routes>`, so it shows on **all pages**. - Placed **outside** `<Routes>`, so it shows on **all pages**.
- The surrounding `<div className="pt-16">` adds space at the top so that page content isnt hidden behind the navbar (assuming the navbar is fixed).
--- ---
## ✅ Checklist for Setting Up Routing ## Setting Up Routing
### 1. **Install React Router** (If you haven't already) - [ ] **Install React Router** (If you haven't already)
```bash ```bash
npm install react-router-dom npm install react-router-dom
``` ```
### 2. **Wrap Your App in Router** - [ ] **Wrap Your App in Router**
```jsx ```jsx
<Router> <Router>
@@ -401,12 +273,21 @@ npm install react-router-dom
</Router> </Router>
``` ```
### 3. **Define Routes** - [ ] **Define Routes**
```jsx ```jsx
<Route path="/" element={<SearchPage />} /> <Route path="/" element={<SearchPage />} />
<Route path="/:vehicleId/:fromCityId/:toCityId" element={<SearchResultsPage />} /> <Route path="/:vehicleId/:fromCityId/:toCityId" element={<SearchResultsPage />} />
``` ```
## 🚧Merge
- [ ] Create a PR and merge the current branch with develop
# 🧠 Hints & Notes
# 🙌 Acknowledgements
- ChatGPT for snippet refinement and explanations
# 🔍 References
# Merge
- [ ] Create a PR and merge the current branch with develop