CustomNavbar.jsx 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import React, { useEffect, useState } from 'react';
  2. import PropTypes from 'prop-types';
  3. import {
  4. Nav, NavItem, NavLink, TabContent, TabPane,
  5. } from 'reactstrap';
  6. import { withTranslation } from 'react-i18next';
  7. import { withUnstatedContainers } from './UnstatedUtils';
  8. import CustomNavbarContainer from '../services/CustomNavbarContainer';
  9. const CustomNavbar = (props) => {
  10. const { t, customNavbarContainer } = props;
  11. const { switchActiveTab } = customNavbarContainer;
  12. const { activeTab } = customNavbarContainer.state;
  13. // [TODO: set default active tab by gw4079]
  14. const [sliderWidth, setSliderWidth] = useState(null);
  15. const [sliderMarginLeft, setSliderMarginLeft] = useState(null);
  16. // Might make this dynamic for px, %, pt, em
  17. function getPercentage(min, max) {
  18. return min / max * 100;
  19. }
  20. const random = Math.random().toString(32).substring(2);
  21. const navTitleId = `custom-navtitle-${random}`;
  22. const navTabId = `custom-navtab-${random}`;
  23. useEffect(() => {
  24. if (activeTab === '') {
  25. return;
  26. }
  27. const navTitle = document.getElementById(navTitleId);
  28. const navTabs = document.querySelectorAll(`li.${navTabId}`);
  29. if (navTitle == null || navTabs == null) {
  30. return;
  31. }
  32. let tempML = 0;
  33. const styles = [].map.call(navTabs, (el) => {
  34. const width = getPercentage(el.offsetWidth, navTitle.offsetWidth);
  35. const marginLeft = tempML;
  36. tempML += width;
  37. return { width, marginLeft };
  38. });
  39. const { width, marginLeft } = styles[props.navTabMapping[activeTab].index];
  40. setSliderWidth(width);
  41. setSliderMarginLeft(marginLeft);
  42. }, [activeTab]);
  43. return (
  44. <React.Fragment>
  45. <Nav className="nav-title" id={navTitleId}>
  46. {Object.entries(props.navTabMapping).map(([key, value]) => {
  47. return (
  48. <NavItem key={key} type="button" className={`p-0 ${navTabId} ${activeTab === key && 'active'}`}>
  49. <NavLink onClick={() => { switchActiveTab(key) }}>
  50. {value.icon}
  51. {value.i18n}
  52. </NavLink>
  53. </NavItem>
  54. );
  55. })}
  56. </Nav>
  57. <hr className="my-0 grw-nav-slide-hr border-none" style={{ width: `${sliderWidth}%`, marginLeft: `${sliderMarginLeft}%` }} />
  58. <TabContent activeTab={activeTab} className="p-5">
  59. {Object.entries(props.navTabMapping).map(([key, value]) => {
  60. return (
  61. <TabPane key={key} tabId={key}>
  62. {value.tabContent}
  63. </TabPane>
  64. );
  65. })}
  66. </TabContent>
  67. </React.Fragment>
  68. );
  69. };
  70. /**
  71. * Wrapper component for using unstated
  72. */
  73. const CustomNavbarWrapper = withUnstatedContainers(CustomNavbar, [CustomNavbarContainer]);
  74. CustomNavbar.propTypes = {
  75. t: PropTypes.func.isRequired, // i18next
  76. customNavbarContainer: PropTypes.instanceOf(CustomNavbarContainer).isRequired,
  77. navTabMapping: PropTypes.object,
  78. };
  79. export default withTranslation()(CustomNavbarWrapper);