fabiobiondi

Tabbar with Generics

Oct 21st, 2020
398
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import React, { useEffect, useState } from 'react';
  2. import cn from 'classnames';
  3.  
  4. interface Country {
  5.   id: number;
  6.   name: string;
  7.   description: string;
  8. }
  9.  
  10. const countries: Country[] = [
  11.   { id: 1, name: 'Japan', description: 'bla bla 1'},
  12.   { id: 2, name: 'Italy', description: 'bla bla 2'},
  13.   { id: 3, name: 'Spain', description: 'bla bla 3'},
  14. ];
  15.  
  16. export default function App() {
  17.   console.log('App: render')
  18.   const [opened, setOpened] = useState<boolean>(true);
  19.   const [active, setActive] = useState<Country>(countries[2])
  20.   const tabClickHandler = (tab: Country) => {
  21.     console.log(tab);
  22.     setActive(tab);
  23.   }
  24.   const tabClickHandler2 = (tab: Country) => {
  25.     console.log(tab);
  26.   }
  27.   return (
  28.      <div className="container mt-2">
  29.        <button onClick={() => setOpened(true)}>OPEN</button>
  30.        <button onClick={() => setOpened(false)}>CLOSE</button>
  31.        <Panel title="hello" style={{ width: 200}} isOpen={opened} toggle={() => console.log('ciao')}>
  32.          <input type="text"/>
  33.          <input type="text"/>
  34.          <input type="text"/>
  35.        </Panel>
  36.  
  37.        <Tabbar <Country>
  38.           data={countries} onTabClick={tabClickHandler} active={active}/>
  39.        <Tabbar data={countries} onTabClick={tabClickHandler2} />
  40.  
  41.        <img src={'https://maps.googleapis.com/maps/api/staticmap?center=' + active.name + '&zoom=5&size=200x100&key=AIzaSyDSBmiSWV4-AfzaTPNSJhu-awtfBNi9o2k'} alt=""/>
  42.        <div>
  43.        {active.description}
  44.        </div>
  45.      {/*  <Tabbar data={....} onTabClick={} active={}></Tabbar>*/}
  46.      </div>
  47.   );
  48. }
  49.  
  50. interface TabbarProps<T> {
  51.   data?: T[];
  52.   active?: T;
  53.   onTabClick: (tab: T) => void
  54. }
  55.  
  56. export const Tabbar = <T extends { id: number, name: string}>(props: TabbarProps<T>) => {
  57.   const [tabActive, setTabActive] = useState<any>()
  58.  
  59.   useEffect(() => {
  60.     setTabActive(props.active);
  61.   }, [ props.active])
  62.  
  63.   function tabClickHAndler(item: any) {
  64.     setTabActive(item);
  65.     props.onTabClick(item);
  66.   }
  67.  
  68.   return (
  69.     <ul className="nav nav-tabs">
  70.       {
  71.         props.data?.map(item => {
  72.           const active = item.id === tabActive?.id;
  73.           return <li key={item.id} className="nav-item" onClick={() => tabClickHAndler(item)}>
  74.             <a className={cn('nav-link', { active })} >{item.name}</a>
  75.           </li>
  76.         })
  77.       }
  78.     </ul>
  79.   )
  80. }
  81.  
  82. // PANEL COMPONENT
  83. interface PanelProps {
  84.   title: string;
  85.   isOpen: boolean;
  86.   toggle?: () => void;
  87. }
  88.  
  89. const Panel: React.FC<PanelProps & React.HTMLProps<HTMLDivElement>> = props => {
  90.   const [opened, setOpened] = useState<boolean>(true);
  91.   const { children, title, isOpen, toggle, ...rest} = props;
  92.  
  93.   useEffect(() => {
  94.     setOpened(props.isOpen);
  95.   }, [ props.isOpen])
  96.  
  97.   function toggleHandler() {
  98.     setOpened(!opened);
  99.     if (props.toggle) {
  100.       props.toggle();
  101.     }
  102.   }
  103.  
  104.   return (
  105.     <div className={'card'} {...rest}>
  106.       <div className={'card-header'} onClick={toggleHandler}>{props.title}</div>
  107.       { opened && <div className="card-body">{props.children} </div>}
  108.     </div>
  109.   )
  110. }
  111.  
Add Comment
Please, Sign In to add comment