Facebook
From Chocolate Sheep, 5 Days ago, written in JavaScript.
Embed
Download Paste or View Raw
Hits: 72
  1. import { useEffect, useMemo, useState } from "react";
  2. import "./styles.css";
  3.  
  4. // busca repositorios
  5. // nome do repo e linguagem
  6.  
  7. interface Repo {
  8.   name: string;
  9.   language: string;
  10. }
  11.  
  12. interface IRepoListProps {
  13.   repoList: Repo[] | null;
  14.   isLoading?: boolean;
  15.   searchLang?: string;
  16. }
  17.  
  18. function RepoList({ repoList, isLoading, searchLang }: IRepoListProps) {
  19.   if (isLoading) return <div>Carregando ...</div>;
  20.  
  21.   if (!repoList) {
  22.     return <div>Não tem nada</div>;
  23.   }
  24.  
  25.   console.log({ repoList });
  26.  
  27.   const filteredRepos = repoList.filter((repo) =>
  28.     repo.language.includes(searchLang)
  29.   );
  30.  
  31.   return (
  32.     <ul>
  33.       {repoList.map((list) => (
  34.         <li key={`list-${list.name}${list.language}`}>
  35.           <div style={{ display: "flex" }}>
  36.             <span style={{ marginRight: "12px" }}>{list.name}</span>
  37.             <strong>{list.language}</strong>
  38.           </div>
  39.         </li>
  40.       ))}
  41.     </ul>
  42.   );
  43. }
  44.  
  45. interface LanguageOptions {
  46.   slug: string;
  47.   name: string;
  48. }
  49.  
  50. function SelectLanguage({
  51.   options,
  52.   onChange
  53. }: {
  54.   options: LanguageOptions[];
  55.   onChange: (value: string | null) => void;
  56. }) {
  57.   const [selectedValue, setValue] = useState<string | null>(null);
  58.  
  59.   useEffect(() => {
  60.     onChange(selectedValue);
  61.   }, [selectedValue]);
  62.  
  63.   return (
  64.     <select
  65.       name="select"
  66.       onChange={(ev) => {
  67.         setValue(ev.target.value);
  68.         // console.log(ev.target.value);
  69.       }}
  70.     >
  71.       <option value={undefined} />
  72.       {options.map(({ slug, name }) => (
  73.         <option key={slug} value={slug}>
  74.           {name}
  75.         </option>
  76.       ))}
  77.     </select>
  78.   );
  79. }
  80.  
  81. const mockLanguages = [
  82.   {
  83.     name: "Javascript",
  84.     slug: "javascript"
  85.   },
  86.   {
  87.     name: "Typescript",
  88.     slug: "typescript"
  89.   }
  90. ];
  91.  
  92. export default function App() {
  93.   const [repos, setRepos] = useState<Repo[] | null>(null);
  94.   const [isLoading, setLoading] = useState(false);
  95.   const [selectedLang, setLang] = useState<string | null>(null);
  96.  
  97.   const url = "https://api.github.com/orgs/vtex/repos?per_page=100";
  98.  
  99.   async function getRepos(url: string) {
  100.     setLoading(true);
  101.     try {
  102.       const response = await fetch(url);
  103.       const result = await response.json();
  104.       return result;
  105.     } catch (err) {
  106.       console.error(err);
  107.     } finally {
  108.       setLoading(false);
  109.     }
  110.   }
  111.  
  112.   useEffect(() => {
  113.     (async () => {
  114.       const fetchResult = await getRepos(url);
  115.       setRepos(fetchResult);
  116.     })();
  117.   }, []);
  118.  
  119.   const memoizedList = useMemo(() => repos, [repos]);
  120.  
  121.   return (
  122.     <div className="App">
  123.       <h2>Vamos começar por aqui</h2>
  124.  
  125.       <SelectLanguage options={mockLanguages} onChange={setLang} />
  126.  
  127.       <RepoList
  128.         isLoading={isLoading}
  129.         repoList={memoizedList}
  130.         searchLang={selectedLang ?? undefined}
  131.       />
  132.     </div>
  133.   );
  134. }
  135.