diff --git a/src/components/rewards/DiscordRewardCard.tsx b/src/components/rewards/DiscordRewardCard.tsx new file mode 100644 index 0000000000..078c90d3aa --- /dev/null +++ b/src/components/rewards/DiscordRewardCard.tsx @@ -0,0 +1,101 @@ +import { useGuild } from "@/app/(dashboard)/[guildUrlName]/hooks/useGuild"; +import { IDENTITY_STYLES } from "@/config/constants"; +import { env } from "@/lib/env"; +import { userOptions } from "@/lib/options"; +import type { GuildReward } from "@/lib/schemas/guildReward"; +import { DiscordRoleRewardDataSchema } from "@/lib/schemas/roleReward"; +import { ArrowSquareOut } from "@phosphor-icons/react/dist/ssr"; +import { useQuery } from "@tanstack/react-query"; +import { useRouter } from "next/navigation"; +import type { FunctionComponent } from "react"; +import { buttonVariants } from "../ui/Button"; +import { + Tooltip, + TooltipContent, + TooltipPortal, + TooltipTrigger, +} from "../ui/Tooltip"; +import { RewardCard, RewardCardButton } from "./RewardCard"; +import type { RewardCardProps } from "./types"; + +export const DiscordRewardCard: FunctionComponent = ({ + reward, +}) => { + const router = useRouter(); + const { + data: { imageUrl, invite }, + } = reward.guildReward as Extract; + const roleRewardData = DiscordRoleRewardDataSchema.parse( + reward.roleReward.data, + ); + + const Icon = IDENTITY_STYLES.DISCORD.icon; + + const { data: user } = useQuery(userOptions()); + const connected = !!user?.identities?.find((i) => i.platform === "DISCORD"); + + const { + data: { id: guildId }, + } = useGuild(); + + const isGuildMember = !!user?.guilds?.find((g) => g.guildId === guildId); + + // TODO: hasRoleAccess instead of isGuildMember + + return ( + } + className={IDENTITY_STYLES.DISCORD.borderColorClassName} + > + {!user || !isGuildMember ? ( + + + Go to server + + + + + +

+ {!user ? "Sign in to proceed" : "Join guild to check access"} +

+
+
+
+ ) : connected ? ( + } + className={IDENTITY_STYLES.DISCORD.buttonColorsClassName} + onClick={() => router.push(`https://discord.gg/${invite}`)} + > + Go to server + + ) : ( + + router.push( + `${env.NEXT_PUBLIC_API}/connect/DISCORD?returnTo=${window.location.href}`, + ) + : undefined + } + > + Connect Discord + + )} +
+ ); +}; diff --git a/src/components/rewards/PointsRewardCard.tsx b/src/components/rewards/PointsRewardCard.tsx index 6ebc0c3174..a61e17bafb 100644 --- a/src/components/rewards/PointsRewardCard.tsx +++ b/src/components/rewards/PointsRewardCard.tsx @@ -12,7 +12,7 @@ export const PointsRewardCard: FunctionComponent = ({ const { id, data: { name }, - } = reward.guildReward as Extract; // Should we use Zod here? + } = reward.guildReward as Extract; const roleRewardData = PointsRoleRewardDataSchema.parse( reward.roleReward.data, ); diff --git a/src/components/rewards/rewardCards.ts b/src/components/rewards/rewardCards.ts index 2ffd1dbbab..eb0ef68ecc 100644 --- a/src/components/rewards/rewardCards.ts +++ b/src/components/rewards/rewardCards.ts @@ -1,7 +1,9 @@ +import { DiscordRewardCard } from "./DiscordRewardCard"; import { GuildPermissionRewardCard } from "./GuildPermissionRewardCard"; import { PointsRewardCard } from "./PointsRewardCard"; export const rewardCards = { GUILD: GuildPermissionRewardCard, POINTS: PointsRewardCard, + DISCORD: DiscordRewardCard, } as const; // TODO: add "satisfies..." diff --git a/src/config/constants.ts b/src/config/constants.ts index d01a1b9c5f..e12cc79449 100644 --- a/src/config/constants.ts +++ b/src/config/constants.ts @@ -4,7 +4,8 @@ import { DiscordLogo } from "@phosphor-icons/react/dist/ssr"; export const IDENTITY_STYLES = { DISCORD: { - mainColorClassName: "bg-indigo-500", + bgColorClassName: "bg-indigo-500", + borderColorClassName: "border-indigo-500", buttonColorsClassName: "bg-indigo-500 hover:bg-indigo-600 active:bg-indigo-700 dark:hover:bg-indigo-400 dark:active:bg-indigo-300", icon: DiscordLogo, @@ -12,7 +13,8 @@ export const IDENTITY_STYLES = { } satisfies Record< IdentityType, { - mainColorClassName: string; + bgColorClassName: string; + borderColorClassName: string; buttonColorsClassName: string; icon: Icon; }