NotificationDetail.tsx 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. import { Archive, ArchiveRestoreIcon, ExternalLink } from 'lucide-react'
  2. import Link from 'next/link'
  3. import { Button } from 'ui'
  4. import { Markdown } from '@/components/interfaces/Markdown'
  5. import { Notification, NotificationData } from '@/data/notifications/notifications-v2-query'
  6. import { useOrganizationsQuery } from '@/data/organizations/organizations-query'
  7. import { useProjectDetailQuery } from '@/data/projects/project-detail-query'
  8. interface NotificationDetailProps {
  9. notification: Notification
  10. onUpdateStatus: (id: string, status: 'archived' | 'seen') => void
  11. }
  12. export const NotificationDetail = ({ notification, onUpdateStatus }: NotificationDetailProps) => {
  13. const data = notification.data as NotificationData
  14. const { data: project } = useProjectDetailQuery({ ref: data.project_ref })
  15. const { data: organizations } = useOrganizationsQuery()
  16. const organization =
  17. data.org_slug !== undefined
  18. ? organizations?.find((org) => org.slug === data.org_slug)
  19. : project !== undefined
  20. ? organizations?.find((org) => org.id === project.organization_id)
  21. : undefined
  22. const onButtonAction = (type?: string) => {
  23. // [Joshen] Implement accordingly - BE team will need to give us a heads up on this
  24. console.log('Action', type)
  25. }
  26. return (
  27. <div>
  28. {(project !== undefined || organization !== undefined) && (
  29. <>
  30. <h3 className="text-sm mb-2">Context</h3>
  31. <div className="flex items-center gap-2 flex-wrap mb-6">
  32. {organization !== undefined && (
  33. <Link
  34. title={organization.name}
  35. href={`/org/${organization.slug}/general`}
  36. className="text-link"
  37. >
  38. {organization.name}
  39. </Link>
  40. )}
  41. {project !== undefined && (
  42. <Link title={project.name} href={`/project/${project.ref}`} className="text-link">
  43. {project.name}
  44. </Link>
  45. )}
  46. </div>
  47. </>
  48. )}
  49. {data.message !== undefined && (
  50. <>
  51. <h3 className="text-sm mb-2">Message</h3>
  52. <Markdown
  53. className="leading-6 text-sm text-foreground-light mb-6"
  54. content={data.message}
  55. />
  56. </>
  57. )}
  58. <h3 className="text-sm mb-2">Actions</h3>
  59. <div className="flex items-center gap-2">
  60. {(data.actions ?? []).map((action, idx) => {
  61. const key = `${notification.id}-action-${idx}`
  62. if (action.url !== undefined) {
  63. const url = action.url.includes('[ref]')
  64. ? action.url.replace('[ref]', project?.ref ?? '_')
  65. : action.url.includes('[slug]')
  66. ? action.url.replace('[slug]', organization?.slug ?? '_')
  67. : action.url
  68. return (
  69. <Button key={key} type="default" icon={<ExternalLink strokeWidth={1.5} />} asChild>
  70. <Link href={url} target="_blank" rel="noreferrer">
  71. {action.label}
  72. </Link>
  73. </Button>
  74. )
  75. } else if (action.action_type !== undefined) {
  76. return (
  77. <Button key={key} type="default" onClick={() => onButtonAction(action.action_type)}>
  78. {action.label}
  79. </Button>
  80. )
  81. } else {
  82. return null
  83. }
  84. })}
  85. {notification.status === 'archived' ? (
  86. <Button
  87. type="default"
  88. icon={<ArchiveRestoreIcon size={14} strokeWidth={1.5} />}
  89. onClick={() => onUpdateStatus(notification.id, 'seen')}
  90. >
  91. Unarchive
  92. </Button>
  93. ) : (
  94. <Button
  95. type="default"
  96. icon={<Archive size={14} strokeWidth={1.5} />}
  97. onClick={() => onUpdateStatus(notification.id, 'archived')}
  98. >
  99. Archive
  100. </Button>
  101. )}
  102. </div>
  103. </div>
  104. )
  105. }