invitations.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. import Link from 'app/ui/atoms/link'
  2. import Profile from 'app/ui/molecules/profile/profile'
  3. import { Text } from 'app/design/typography'
  4. import { View, Row } from 'app/design/view'
  5. import { fetcher } from 'app/lib/fetcher';
  6. import { useState } from 'react';
  7. import { NeoButtonLink, NeoButton } from 'app/design/controls'
  8. import Image from 'app/ui/atoms/image'
  9. import ProfilesList from 'app/ui/molecules/profile/profile-list'
  10. import { useTranslation } from 'react-i18next';
  11. import { CardList } from 'app/ui/molecules/page/card'
  12. import { tp } from 'app/lib/util'
  13. export default function Unit(props) {
  14. const { t } = useTranslation();
  15. const [state, setState] = useState(false);
  16. const data = props.data
  17. const friendsLabel = data.members_count > 0 ? tp("members", data?.members_count) : ''
  18. const processInvitation = async (request_url) => {
  19. await fetcher(request_url);
  20. setState(true);
  21. }
  22. if (state) return
  23. // for separate page
  24. if (props.unitType == 'invitations_in_context') {
  25. return (
  26. <CardList padding='p-2' className='mb-2 md:mb-0'>
  27. <Link className="context " href={data.url}>
  28. <View className="flex-row sm:flex-col p-1">
  29. <View className="aspect-square sm:aspect-video w-1/3 sm:w-full rounded-xl overflow-hidden items-center justify-center bg-muted-foreground/20">
  30. <Image
  31. {...data.cover}
  32. alt={data.title}
  33. view="cover"
  34. className="absolute u-cover rounded-lg"
  35. sizes='auto'
  36. />
  37. </View>
  38. <View className="p-3 flex-auto items-between justify-between ">
  39. <View>
  40. <Text numberOfLines={2} className="text-card-foreground tracking-tight web:hover:text-foreground web:hover:underline leading-tight font-semibold">
  41. {data.title}
  42. </Text>
  43. <Row className="items-center h-6 my-3">
  44. <View className="mr-2 h-6">
  45. <ProfilesList
  46. data={
  47. data.members_list
  48. }
  49. showEmpty={false}
  50. maxCount={3}
  51. displaySize="xs"
  52. />
  53. </View>
  54. {
  55. <Text className="truncate text-xs leading-tight flex-auto text-muted-foreground ">
  56. {friendsLabel}
  57. </Text>
  58. }
  59. <Text className=" bg-primary/10 rounded-md px-1.5 py-1 text-xs flex-none items-center font-semibold text-muted-foreground ">
  60. {data.visibility != "3" ? t('Private') : t('Public')}
  61. </Text>
  62. </Row>
  63. </View>
  64. <View className="flex-row w-full gap-x-2">
  65. {!!data.callback_accept && <NeoButton style="borderedProminent" controlSize="small" width="fill" label={t('Accept')} expoUI={false} onPress={() => { processInvitation(data.callback_accept) }} />}
  66. {!!data.callback_decline && <NeoButton controlSize="small" width="fill" label={t('Decline')} expoUI={false} onPress={() => { processInvitation(data.callback_decline) }} />}
  67. {!!data.redirect_url && <NeoButtonLink href={data.redirect_url} controlSize="small" width="fill" label={data.redirect_title} />}
  68. </View>
  69. </View>
  70. </View>
  71. </Link>
  72. </CardList>
  73. )
  74. }
  75. return (
  76. <Link variant='ghost' size='lg' href={data.url} emulate={true}>
  77. <View
  78. className=" flex-row gap-2 items-center max-w-4xl mx-auto w-full"
  79. >
  80. <Profile
  81. url_avatar={data?.image?.src}
  82. displayType="unit_wo_info"
  83. displaySize="md"
  84. display_name={data.title}
  85. />
  86. <View className="flex-row justify-between flex-auto items-center">
  87. <Text numberOfLines={2} className="text-sm leading-tight font-semibold text-card-foreground web:group-hover:text-foreground ">
  88. {data.title}
  89. </Text>
  90. <View className="flex-none">
  91. <Row className='gap-2'>
  92. {!!data.callback_accept && <NeoButton style="borderedProminent" controlSize="mini" borderShape="capsule" label={t('Accept')} expoUI={false} onPress={() => { processInvitation(data.callback_accept) }} />}
  93. {!!data.callback_decline && <NeoButton controlSize="mini" borderShape="circle" image="X" accessibilityLabel={t('Decline')} expoUI={false} onPress={() => { processInvitation(data.callback_decline) }} />}
  94. {!!data.redirect_url && <NeoButtonLink href={data.redirect_url} controlSize="mini" width="fill" label={data.redirect_title} />}
  95. </Row>
  96. </View>
  97. </View>
  98. </View>
  99. </Link>
  100. )
  101. }