ReviewRow.tsx 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. import { useQueryClient } from '@tanstack/react-query'
  2. import dayjs from 'dayjs'
  3. import { MoreVertical, X } from 'lucide-react'
  4. import { useRouter } from 'next/router'
  5. import { toast } from 'sonner'
  6. import {
  7. Button,
  8. DropdownMenu,
  9. DropdownMenuContent,
  10. DropdownMenuItem,
  11. DropdownMenuTrigger,
  12. } from 'ui'
  13. import { useBranchUpdateMutation } from '@/data/branches/branch-update-mutation'
  14. import type { Branch } from '@/data/branches/branches-query'
  15. import { branchKeys } from '@/data/branches/keys'
  16. interface ReviewRowProps {
  17. branch: Branch
  18. }
  19. export const ReviewRow = ({ branch }: ReviewRowProps) => {
  20. const router = useRouter()
  21. const queryClient = useQueryClient()
  22. const { project_ref: branchRef, parent_project_ref: projectRef } = branch
  23. const { mutate: updateBranch, isPending: isUpdating } = useBranchUpdateMutation({
  24. onSuccess: () => {
  25. toast.success('Branch marked as not ready for review')
  26. queryClient.invalidateQueries({
  27. queryKey: branchKeys.list(projectRef),
  28. })
  29. },
  30. onError: (error) => {
  31. toast.error(`Failed to update branch: ${error.message}`)
  32. },
  33. })
  34. const handleRowClick = () => {
  35. router.push(`/project/${branchRef}/merge`)
  36. }
  37. const handleNotReadyForReview = (e?: Event) => {
  38. e?.preventDefault()
  39. e?.stopPropagation()
  40. updateBranch({
  41. branchRef,
  42. projectRef,
  43. requestReview: false,
  44. })
  45. }
  46. const formattedReviewDate = branch.review_requested_at
  47. ? dayjs(branch.review_requested_at).format('MMM DD, YYYY HH:mm')
  48. : ''
  49. return (
  50. <div
  51. className="w-full flex items-center justify-between px-6 py-3 hover:bg-surface-100 cursor-pointer transition-colors"
  52. onClick={handleRowClick}
  53. >
  54. <div className="flex items-center gap-x-4">
  55. <div className="flex gap-4">
  56. <h4 className="text-sm text-foreground" title={branch.name}>
  57. {branch.name}
  58. </h4>
  59. <p className="text-foreground-light">{formattedReviewDate}</p>
  60. </div>
  61. </div>
  62. <div className="flex items-center gap-x-2">
  63. <DropdownMenu>
  64. <DropdownMenuTrigger asChild>
  65. <Button
  66. type="text"
  67. icon={<MoreVertical />}
  68. className="px-1"
  69. onClick={(e) => e.stopPropagation()}
  70. />
  71. </DropdownMenuTrigger>
  72. <DropdownMenuContent className="w-56" side="bottom" align="end">
  73. <DropdownMenuItem
  74. className="gap-x-2"
  75. disabled={isUpdating}
  76. onClick={(e) => e.stopPropagation()}
  77. onSelect={handleNotReadyForReview}
  78. >
  79. <X size={14} />
  80. Not ready for review
  81. </DropdownMenuItem>
  82. </DropdownMenuContent>
  83. </DropdownMenu>
  84. </div>
  85. </div>
  86. )
  87. }