-
- {bounty.rewardAmount != null
- ? `$${bounty.rewardAmount.toLocaleString()}`
- : "TBD"}
-
-
- {bounty.rewardCurrency}
-
+
+
+ {/* Reward */}
+
+
+ Reward
+
+
+
+ {bounty.rewardAmount != null
+ ? `$${bounty.rewardAmount.toLocaleString()}`
+ : "TBD"}
+
+
+ {bounty.rewardCurrency}
+
+
-
-
-
- {/* Meta */}
-
-
- Status
-
-
-
-
Type
-
+
+
+ {/* Meta */}
+
+
+ Status
+
+
+
+ Type
+
+
-
-
-
- {/* CTA */}
-
-
- {!canAct && (
-
-
- This bounty is no longer accepting new submissions.
-
- )}
-
- {/* GitHub */}
-
-
- View on GitHub
-
-
- {/* Copy link */}
-
+
+ {/* GitHub */}
+
+
+ View on GitHub
+
+
+ {/* Copy link */}
+
+ {copied ? (
+ <>
+
+ Copied!
+ >
+ ) : (
+ <>
+
+ Copy link
+ >
+ )}
+
+
);
}
diff --git a/hooks/use-bounty-mutations.ts b/hooks/use-bounty-mutations.ts
index 37063dc..d6e31fd 100644
--- a/hooks/use-bounty-mutations.ts
+++ b/hooks/use-bounty-mutations.ts
@@ -1,98 +1,111 @@
-import { useMutation, useQueryClient } from '@tanstack/react-query';
+import { useMutation, useQueryClient } from "@tanstack/react-query";
import {
- bountiesApi,
- type Bounty,
- type CreateBountyInput,
- type UpdateBountyInput,
- type PaginatedResponse,
-} from '@/lib/api';
-import { bountyKeys } from './use-bounties';
+ bountiesApi,
+ type Bounty,
+ type CreateBountyInput,
+ type UpdateBountyInput,
+ type PaginatedResponse,
+} from "@/lib/api";
+import { bountyKeys } from "./use-bounties";
export function useCreateBounty() {
- const queryClient = useQueryClient();
+ const queryClient = useQueryClient();
- return useMutation({
- mutationFn: (data: CreateBountyInput) => bountiesApi.create(data),
- onSuccess: () => {
- queryClient.invalidateQueries({ queryKey: bountyKeys.lists() });
- },
- });
+ return useMutation({
+ mutationFn: (data: CreateBountyInput) => bountiesApi.create(data),
+ onSuccess: () => {
+ queryClient.invalidateQueries({ queryKey: bountyKeys.lists() });
+ },
+ });
}
export function useUpdateBounty() {
- const queryClient = useQueryClient();
+ const queryClient = useQueryClient();
- return useMutation({
- mutationFn: ({ id, data }: { id: string; data: UpdateBountyInput }) =>
- bountiesApi.update(id, data),
- onMutate: async ({ id, data }) => {
- await queryClient.cancelQueries({ queryKey: bountyKeys.detail(id) });
- const previous = queryClient.getQueryData
(bountyKeys.detail(id));
+ return useMutation({
+ mutationFn: ({ id, data }: { id: string; data: UpdateBountyInput }) =>
+ bountiesApi.update(id, data),
+ onMutate: async ({ id, data }) => {
+ await queryClient.cancelQueries({ queryKey: bountyKeys.detail(id) });
+ const previous = queryClient.getQueryData(bountyKeys.detail(id));
- if (previous) {
- queryClient.setQueryData(bountyKeys.detail(id), {
- ...previous,
- ...data,
- updatedAt: new Date().toISOString(),
- });
- }
+ if (previous) {
+ queryClient.setQueryData(bountyKeys.detail(id), {
+ ...previous,
+ ...data,
+ updatedAt: new Date().toISOString(),
+ });
+ }
- return { previous, id };
- },
- onError: (_err, _vars, context) => {
- if (context?.previous) {
- queryClient.setQueryData(bountyKeys.detail(context.id), context.previous);
- }
- },
- onSettled: (_data, _err, { id }) => {
- queryClient.invalidateQueries({ queryKey: bountyKeys.detail(id) });
- queryClient.invalidateQueries({ queryKey: bountyKeys.lists() });
- },
- });
+ return { previous, id };
+ },
+ onError: (_err, _vars, context) => {
+ if (context?.previous) {
+ queryClient.setQueryData(
+ bountyKeys.detail(context.id),
+ context.previous,
+ );
+ }
+ },
+ onSettled: (_data, _err, { id }) => {
+ queryClient.invalidateQueries({ queryKey: bountyKeys.detail(id) });
+ queryClient.invalidateQueries({ queryKey: bountyKeys.lists() });
+ },
+ });
}
export function useDeleteBounty() {
- const queryClient = useQueryClient();
+ const queryClient = useQueryClient();
- return useMutation({
- mutationFn: (id: string) => bountiesApi.delete(id),
- onMutate: async (id) => {
- await queryClient.cancelQueries({ queryKey: bountyKeys.lists() });
+ return useMutation({
+ mutationFn: (id: string) => bountiesApi.delete(id),
+ onMutate: async (id) => {
+ await queryClient.cancelQueries({ queryKey: bountyKeys.lists() });
- const previousLists = queryClient.getQueriesData>({
- queryKey: bountyKeys.lists(),
- });
+ const previousLists = queryClient.getQueriesData<
+ PaginatedResponse
+ >({
+ queryKey: bountyKeys.lists(),
+ });
- queryClient.setQueriesData>(
- { queryKey: bountyKeys.lists() },
- (old) => old ? {
- ...old,
- data: old.data.filter((b) => b.id !== id),
- pagination: { ...old.pagination, total: old.pagination.total - 1 },
- } : old
- );
+ queryClient.setQueriesData>(
+ { queryKey: bountyKeys.lists() },
+ (old) =>
+ old
+ ? {
+ ...old,
+ data: old.data.filter((b) => b.id !== id),
+ pagination: {
+ ...old.pagination,
+ total: old.pagination.total - 1,
+ },
+ }
+ : old,
+ );
- return { previousLists };
- },
- onError: (_err, _id, context) => {
- context?.previousLists.forEach(([key, data]) => {
- queryClient.setQueryData(key, data);
- });
- },
- onSettled: () => {
- queryClient.invalidateQueries({ queryKey: bountyKeys.lists() });
- },
- });
+ return { previousLists };
+ },
+ onError: (_err, _id, context) => {
+ context?.previousLists.forEach(([key, data]) => {
+ queryClient.setQueryData(key, data);
+ });
+ },
+ onSettled: () => {
+ queryClient.invalidateQueries({ queryKey: bountyKeys.lists() });
+ },
+ });
}
export function useClaimBounty() {
- const queryClient = useQueryClient();
+ const queryClient = useQueryClient();
- return useMutation({
- mutationFn: (id: string) => bountiesApi.claim(id),
- onSuccess: (data, id) => {
- queryClient.setQueryData(bountyKeys.detail(id), data);
- queryClient.invalidateQueries({ queryKey: bountyKeys.lists() });
- },
- });
+ return useMutation({
+ mutationFn: (id: string) => bountiesApi.claim(id),
+ onSuccess: (data, id) => {
+ queryClient.setQueryData(bountyKeys.detail(id), data);
+
+ // Invalidate the list view so the main bounties board updates
+ queryClient.invalidateQueries({ queryKey: bountyKeys.lists() });
+ },
+ });
}