### 代碼倉 [https://github.com/WilsonCode1224/Anime-search](https://github.com/WilsonCode1224/Anime-search) ### 待修正事項: - 11/20 待修正事項: - [x] isSearch 應該要用 dispatch - [x] HomePage 用 Map - [x] AnimaItem map - [x] Iframe 意義 - [x] Upcoming render() + map問題 (目前合併起來解決。) - [x] 額外 濃縮成一個 component Airing/Popular/UpComing ### 11/20 工作日誌: 1. 11:30 ~ 12:00 - 調整 網址 URL 結構。 2. 12:00 ~ 12:30 - HomePage 用 Map。 ```jsx // 2. Header Button const HeaderButtons = (setRendered, getAiringAnime, getUpcomingAnime) => [ { label: "Popular", onClick: () => { setRendered("popular"); }, icon: <i className="fas fa-fire" />, }, { label: "Airing", onClick: () => { setRendered("airing"); getAiringAnime(); }, }, { label: "Upcoming", onClick: () => { setRendered("upcoming"); getUpcomingAnime(); }, }, ]; // render {buttons.map((button, index) => ( <div key={index} className={button.className}> <button onClick={button.onClick}> {button.icon} {button.label} </button> </div> ))} ``` 3. 12:30 ~ 13:00 - AnimaItem map ```jsx const detailsData = [ { label: "Aired", data: aired?.string }, { label: "Rating", data: rating }, { label: "Rank", data: rank }, { label: "Score", data: score }, { label: "Scored By", data: scored_by }, { label: "Popularity", data: popularity }, { label: "Status", data: status }, { label: "Source", data: source }, { label: "Season", data: season }, { label: "Duration", data: duration }, ]; // render <div className="anime-details"> {detailsData.map((detail, index) => ( <p key={index}> <span>{detail.label}</span> <span>{detail.data}</span> </p> ))} </div> ``` 4. 13:00 ~ 13:30 Iframe 是什麼東西? - iframe,是一個 HTML 標籤。 用來嵌入其他 HTML 文件或外部網頁。 - 在該專案也有使用到這個 Tag: 使用來嵌入動畫的預告片(trailer)。 這樣的做法使得動畫的預告片可以直接在你的網頁上播放,而不需要跳轉到其他頁面或網站。 ```jsx <div className="trailer-con"> {trailer?.embed_url ? ( <iframe src={trailer?.embed_url} title="Inline Frame Example" width="800" height="450" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowFullScreen ></iframe> ) : ( <h3>Trailer not available</h3> )} </div> ``` 5. 13:40 ~ 14:15 isSearch 應該要用 dispatch ```jsx // add actions // actions const LOADING = "LOADING"; const SEARCH = "SEARCH"; const GET_POPULAR_ANIME = "GET_POPULAR_ANIME"; const GET_UPCOMING_ANIME = "GET_UPCOMING_ANIME"; const GET_AIRING_ANIME = "GET_AIRING_ANIME"; const GET_PICTURES = "GET_PICTURES"; const IS_SEARCH = "IS_SEARCH"; // 1 const IS_NOT_SEARCHING = "IS_NOT_SEARCHING"; // 2 // actions type // reducer const reducer = (state, action) => { switch (action.type) { case LOADING: return { ...state, loading: true }; case GET_POPULAR_ANIME: return { ...state, popularAnime: action.payload, loading: false }; case SEARCH: return { ...state, searchResults: action.payload, loading: false }; case GET_UPCOMING_ANIME: return { ...state, upcomingAnime: action.payload, loading: false }; case GET_AIRING_ANIME: return { ...state, airingAnime: action.payload, loading: false }; case GET_PICTURES: return { ...state, pictures: action.payload, loading: false }; case IS_SEARCH: return { ...state, isSearch: true }; case IS_NOT_SEARCHING: return { ...state, isSearch: false }; default: return state; } }; // 不要直接針對屬性控制 , 透過 dispatch 操作 const handleSubmit = (e) => { e.preventDefault(); if (search) { searchAnime(search); // 異步函數 dispatch({ type: IS_SEARCH }); } else { dispatch({ type: IS_NOT_SEARCHING }); alert("Please enter a search term"); } }; ``` 6. 14:15 ~ 14:40 中場休息,部署一下網站。 - 自嗨一下(?) ![截圖 2023-11-20 下午3.16.48](https://hackmd.io/_uploads/S1T1OYdNT.png) 7. 15:00 ~ 17:00 額外濃縮成一個 component **Airing/Popular/UpComing**: - 1. 建立一個整合邏輯的元件 - AnimatedList.jsx。 - 2. 將 AnimatedList.jsx 導入到 Homepage.jsx。 --- ### 11/21 工作日誌: - 待處理的 bugs、優化網站等細項: - [x] 用戶搜尋資料以後,無法透過按鈕去取得對應的動漫資訊。 ### 11/22 工作日誌: - [x] - 研究 API 資料,看能不能,找出動漫分類。 ```jsx // 目前 data.data 可以查到的 types: const getAnimeGenres = async () => { // genres/anime const response = await fetch( `https://api.jikan.moe/v4/top/anime?filter=bypopularity` ); const data = await response.json(); console.log(data.data[0].genres[0].name); }; // console.log(item.genres[0].name); -> 11/22 14:05 ``` - [x] - 動漫分類過濾,開發元件或新功能。 - (有素材) ``` 進度描述: 1. 目前僅能將 popularAnime [] 資料傳進來, 以這邊的資料為準設置了動漫分類,套用到 MUI 素材,並且開立一個分頁。 後續會先以 popular , airing , upcoming 的資料來源來去做分類寫邏輯。 // 日後 api 資料有時間再做一個 Total 的 Filter。 ``` ![截圖 2023-11-22 下午3.25.58](https://hackmd.io/_uploads/r17MTXjNa.png) #### bug 修改及詠唱反饋: 1. 目前可以透過點擊 radio,type === 取得關聯的動畫。 ``` UI 控制,切換 Light、Dark 模式,進度描述: 詠唱出了一段 UI,但真他媽醜 xd 目前還沒辦法控制全局套用。 ``` --- ### 11/23 工作日誌: - 螢幕右下方有一個齒輪: - 點擊以後可以出現: - [x] - 齒輪設定完成,目前點擊可以產生更多查詢的面板。 - 「查詢更多熱門分類」- popular。 - 「查詢更多上映分類」- aircoming。 - 「查詢更多待上映分類」- upcoming。 --- ### 11/24 工作日誌: - [x] - 透過 context,取得三份 initial State 資料原型。 - [ ] - 將上述功能畫面整合成一個元件: - 該元件可將三份來源資料整合在該元件「SearchMore.jsx」 - 且點擊路由,就可取得對應的分類 radio,及其對應的動畫。 - [ ] - UI 開發,以 styled 為主要樣式開發工具。 - [x] - 控制 Setting 路由 -> 熱門動畫 -> 取得資料。 --- ### 11/25 工作日誌: - [x] - 點擊 SearchMore 選單,可以取消 AnimatedList。 - 棘手問題:因為一開始需要先載入 popular,有什麼辦法可以取消? - [X] - 點擊以後,已經可以正確來回切換 AnimatedList。 1. ```jsx // 修改內容: // context add State -> 傳遞到: const [showAnimatedList, setShowAnimatedList] = useState(true); // 控制 AnimatedList View ``` 2. 確認哪些元件有相對應的關聯性: - **Homepage:** ```jsx // Homepage, HeaderButtons 變數: const HeaderButtons = ( setRendered, getAiringAnime, getUpcomingAnime // getPopularAnime ) => { // 沒有這個 setState , 無法接收控制狀態。 const { setShowAnimatedList } = useGlobalContext(); return [ { label: "Popular", onClick: () => { setRendered("popular"); setShowAnimatedList(true); // 显示 AnimatedList }, icon: <i className="fas fa-fire" />, }, { label: "Airing", onClick: () => { setRendered("airing"); getAiringAnime(); setShowAnimatedList(true); // 显示 AnimatedList }, }, { label: "Upcoming", onClick: () => { setRendered("upcoming"); getUpcomingAnime(); setShowAnimatedList(true); // 显示 AnimatedList }, }, ]; }; // Homepage jsx render: <AnimatedList rendered={rendered} showAnimatedList={showAnimatedList} /> ``` 3. AnimatedList 需要這個 props: ```jsx function AnimatedList({ rendered, showAnimatedList }) { if (!showAnimatedList) { return null; // 不渲染 AnimatedList (表示不是 true 就 null 掉) } const { popularAnime, airingAnime, upcomingAnime, isSearch, searchResults } = useGlobalContext(); const getAnimeData = (rendered) => { switch (rendered) { case "popular": return popularAnime; case "airing": return airingAnime; case "upcoming": return upcomingAnime; default: return popularAnime; } }; ``` - [x] - 測試:可以透過路由點擊以後,顯示 MorePopular! - [x] - 透過點擊 SearchMore - 先去做到切換取得更多分類的「標題」。 - [X] - 標題切換以後,標題去判斷使組件去判別該從 Context 取得什麼「資料」。 ```jsx 功能 & 邏輯已經完成,這邊需要在研究一下 MorePopular 組件邏輯。 ``` ### 11/26 工作日誌: - [x] 釐清:Homepage、MoreSearch、MorePopular 元件新增語法。 #### 1. 在 Homepage 右下角,設置了一個 Setting Icon: - 用戶點擊以後,會在左方顯示一下展開的 Box,這邊是如何運作? ```jsx // 1. 首先要在 Homepage.jsx 設置一個元件,這表示 SearchMore import SearchMore from "./SearchMore"; -> 導入這塊元件。 // 2. 插入 render 元件 -> <SearchMore setShowMorePopular={setShowMorePopular} handleCategoryClick={handleCategoryClick} /> // 3. 在 gobalContext 設置好 控制用的 State: const [openSetting, setOpenSetting] = useState(false); // 4. 並且傳入到 Children 給上下文傳遞在為一個使用: - 這邊範例是直接在 SearchMore 做傳遞了: const { openSetting, // 打開樣版的 State setOpenSetting, // 打開樣版的 setState // 以下略過 ... } = useGlobalContext(); ``` ```jsx // 5. 為何點擊之後可以產生及關閉搜索更多分類? 原因如下: <Link> <FixedSettingsIcon style={{ width: "40px", height: "40px" }} // 6. 由於 setOpenSetting 預設為 false 所以點擊之後反向自然會變成 true。 onClick={() => setOpenSetting(!openSetting)} /> </Link> ``` ```jsx // 7. 下面則是顯現,當 openSetting true 時則會渲染以下內容: {openSetting && ( // -> 相對的點擊後 false 則是隱藏 <SettingPanel> <SearchTitle> Search More Anime {/* <SearchIcon className="search-icon" /> */} </SearchTitle> <ShowText> {SearchText.map((item, index) => ( <div key={index}> <Link to="#" onClick={() => handleLinkClick(item.action)}> {item.showText} </Link> </div> ))} </ShowText> </SettingPanel> )} // 8. 而項目列表則是由 map method 方法跑出來的。 ``` #### 2. 搜尋更多的路由,是怎麼去根據邏輯產生分類搜尋的? - SearchMore 點擊路由,以後會去關閉 AnimatedList。 - 切換成 MorePopular - 並且根據路由名稱去顯示對應的資料分類。 ```jsx // 1. 我們在前面有使用 map 去渲染路由,並且這些路由都會呼叫一個回調函數在上面。 <ShowText> {SearchText.map((item, index) => ( <div key={index}> <Link to="#" onClick={() => handleLinkClick(item.action)}> // 在這邊 {item.showText} </Link> </div> ))} </ShowText> // 2. 用戶點擊連結,呼叫回調函數以後,讓我們來看到回調函數的內容: // 3. 此時,我們可以根據我們所處的 action.type 去執行對應的 case 內容。 const handleLinkClick = (action) => { // 根據點擊的連結,調用相應的函數 switch (action) { case "getPopularAnime": // 這邊暫時不設置任何東西,因為熱門動畫會在一開始就載入。 handleCategoryClick("popular"); // 告之父元素,現在做了哪些事? break; case "getAiringAnime": getAiringAnime(); handleCategoryClick("airing"); // 告之父元素,現在做了哪些事? break; case "getUpcomingAnime": getUpcomingAnime(); handleCategoryClick("upcoming"); // 告之父元素,現在做了哪些事? break; default: console.log("default case!"); break; } setOpenSetting(!openSetting); // 關閉樣版 // ShowAnimatedList 是 context 傳進來的 setShowAnimatedList(false); // 更新 AnimatedList 為 false setShowMorePopular(true); // 更新 MorePopular 為 true -> 上面這兩個 setState 則是關鍵了,並將這些更新資訊 作為 props 傳遞到 Homepage 元件 }; // 4. props 怎麼傳遞? - 從這邊: function SearchMore({ setShowMorePopular, handleCategoryClick }) {} ``` ```jsx // 5. 回到 Home 父組件: - 這邊可以看到,子組件 SearchMore 設置了兩個 props // renoder: <SearchMore // 控制點擊分類的分類 handleCategoryClick={handleCategoryClick} // 顯示 MorePopular setShowMorePopular={setShowMorePopular} /> // 從子元件的 props 傳遞資訊,回到 Homepage 元件這邊的代碼: -> 這邊傳遞的 category 參數會帶入到 setSelectedCategory const handleCategoryClick = (category) => { setSelectedCategory(category); }; // selectedCategory 的 State const [selectedCategory, setSelectedCategory] = useState(null); // 這邊是 SearchMore 的部分 -> 根據上面所傳遞進來的資訊,selectedCategory(切換category) // -> render , 此時根據傳遞到上面代碼的 category 繼續傳遞到子組件 去做相對應的渲染結果: {showMorePopular && <MorePopular selectedCategory={selectedCategory} />} -> 這段代碼表示: 當 showMorePopular true 時,則顯示 MorePopular 組件, 並且將 selectedCategory 狀態藉由 props 的形式傳遞到下個組件使用。 (MorePopular) ``` #### 3. MorePopular 怎麼去決定渲染的分類。 - 根據三個路由的條件,去決定資料來源且顯示更多的 radio 選項: ```jsx // 1. 根據上述的流程,影響 MorePopular 組件條件就是 Props: {showMorePopular && <MorePopular selectedCategory={selectedCategory} />} // 2. 根據傳遞的 props - selectedCategory 決定代碼的走向 oops , 這裏目前遇到了一些不太能理解的 bug , 待修正。 (暫時不影響結果) ``` --- ### 11/27 工作日誌: - [X] 確認一下需要 RWD 開發的部分。 ``` // Homepage - 顯示更多搜尋的 Icon fixed 定位。 --- O // 點擊 Icon fixed 以後,左側欄位顯示。 --- O // 搜尋結果的圖片位置 - center。 --- O // 點擊動漫清單,裡面的 RWD 修飾。 --- X ``` - [ ] 設計 UI,'Dark' & 'Light' mode 控制設計。 - [x] RWD 各種修理! --- 目前大概只剩點擊後的 AnimeItem.jsx - [x] HomePage - [x] SearchMore - [x] AnimeItem ### 11/30 工作日誌: - [ ] - UI 控制,切換 Light、Dark 模式。 ([有素材] ### 12/1 工作日誌: - [ ] - i18n 繁中化 zh? ### 待處理的任務: - 該專案目前預計執行的項目: (https://mui.com/material-ui/react-switch/)) - [ ] 把 className 換成 styled(CSS) - [ ] i18n (中文化) - [ ] global getAnime 函數封裝 --- - 未來有機會在修改的東西: - [ ] - 增設我的最愛,至收藏頁面功能。 - [ ] 網址 URL 結構 / 認識一下。(知識) - [ ] 瀏覽器引擎 發展史。(知識) - [ ] build / bundler。(知識)