index.tsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. import { Fragment } from 'react'
  2. import { useContext } from 'use-context-selector'
  3. import { useTranslation } from 'react-i18next'
  4. import { Menu, Transition } from '@headlessui/react'
  5. import s from './index.module.css'
  6. import cn from '@/utils/classnames'
  7. import { switchWorkspace } from '@/service/common'
  8. import { useWorkspacesContext } from '@/context/workspace-context'
  9. import { ChevronRight } from '@/app/components/base/icons/src/vender/line/arrows'
  10. import { Check } from '@/app/components/base/icons/src/vender/line/general'
  11. import { ToastContext } from '@/app/components/base/toast'
  12. import classNames from '@/utils/classnames'
  13. const itemClassName = `
  14. flex items-center px-3 py-2 h-10 cursor-pointer
  15. `
  16. const itemIconClassName = `
  17. shrink-0 mr-2 flex items-center justify-center w-6 h-6 bg-[#EFF4FF] rounded-md text-xs font-medium text-primary-600
  18. `
  19. const itemNameClassName = `
  20. grow mr-2 text-sm text-gray-700 text-left
  21. `
  22. const itemCheckClassName = `
  23. shrink-0 w-4 h-4 text-primary-600
  24. `
  25. const WorkplaceSelector = () => {
  26. const { t } = useTranslation()
  27. const { notify } = useContext(ToastContext)
  28. const { workspaces } = useWorkspacesContext()
  29. const currentWorkspace = workspaces.find(v => v.current)
  30. const handleSwitchWorkspace = async (tenant_id: string) => {
  31. try {
  32. if (currentWorkspace?.id === tenant_id)
  33. return
  34. await switchWorkspace({ url: '/workspaces/switch', body: { tenant_id } })
  35. notify({ type: 'success', message: t('common.actionMsg.modifiedSuccessfully') })
  36. location.assign(`${location.origin}`)
  37. }
  38. catch (e) {
  39. notify({ type: 'error', message: t('common.provider.saveFailed') })
  40. }
  41. }
  42. return (
  43. <Menu as="div" className="relative w-full h-full">
  44. {
  45. ({ open }) => (
  46. <>
  47. <Menu.Button className={cn(
  48. `
  49. ${itemClassName} w-full
  50. group hover:bg-state-base-hover cursor-pointer ${open && 'bg-state-base-hover'} rounded-lg
  51. `,
  52. )}>
  53. <div className={itemIconClassName}>{currentWorkspace?.name[0].toLocaleUpperCase()}</div>
  54. <div className={`${itemNameClassName} truncate`}>{currentWorkspace?.name}</div>
  55. <ChevronRight className='shrink-0 w-[14px] h-[14px] text-gray-500' />
  56. </Menu.Button>
  57. <Transition
  58. as={Fragment}
  59. enter="transition ease-out duration-100"
  60. enterFrom="transform opacity-0 scale-95"
  61. enterTo="transform opacity-100 scale-100"
  62. leave="transition ease-in duration-75"
  63. leaveFrom="transform opacity-100 scale-100"
  64. leaveTo="transform opacity-0 scale-95"
  65. >
  66. <Menu.Items
  67. className={cn(
  68. `
  69. absolute top-[1px] min-w-[200px] max-h-[70vh] overflow-y-scroll z-10 bg-white border-[0.5px] border-gray-200
  70. divide-y divide-gray-100 origin-top-right rounded-xl focus:outline-none
  71. `,
  72. s.popup,
  73. )}
  74. >
  75. <div className="px-1 py-1">
  76. {
  77. workspaces.map(workspace => (
  78. <Menu.Item key={workspace.id}>
  79. {({ active }) => <div className={classNames(itemClassName,
  80. active && 'bg-state-base-hover',
  81. )} key={workspace.id} onClick={() => handleSwitchWorkspace(workspace.id)}>
  82. <div className={itemIconClassName}>{workspace.name[0].toLocaleUpperCase()}</div>
  83. <div className={itemNameClassName}>{workspace.name}</div>
  84. {workspace.current && <Check className={itemCheckClassName} />}
  85. </div>}
  86. </Menu.Item>
  87. ))
  88. }
  89. </div>
  90. </Menu.Items>
  91. </Transition>
  92. </>
  93. )
  94. }
  95. </Menu>
  96. )
  97. }
  98. export default WorkplaceSelector