-
Notifications
You must be signed in to change notification settings - Fork 448
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* refactor(AddRoleRewardModal): WIP * refactor: AddRewardButton WIP * fix: bringing back previous functionality * refactor(SelectRewardPanel): composition to pass SelectExistingPlatform as children * remove duplicated ModalContent from SelectRolePanel * refactor: create useSubmitAddReward hook * dynamic reward modal width, move ModalContent into rendered components so it animates on every change * cleanup(AddRoleRewardModal): remove impossible SelectRoleOrSetRequirements state --------- Co-authored-by: valid <valid@zgen.hu>
- Loading branch information
Showing
23 changed files
with
872 additions
and
769 deletions.
There are no files selected for viewing
372 changes: 45 additions & 327 deletions
372
src/components/[guild]/AddRewardButton/AddRewardButton.tsx
Large diffs are not rendered by default.
Oops, something went wrong.
151 changes: 151 additions & 0 deletions
151
src/components/[guild]/AddRewardButton/SelectRolePanel.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
import { | ||
HStack, | ||
IconButton, | ||
ModalBody, | ||
ModalCloseButton, | ||
ModalContent, | ||
ModalFooter, | ||
ModalHeader, | ||
Stack, | ||
Text, | ||
Tooltip, | ||
useColorModeValue, | ||
} from "@chakra-ui/react" | ||
import Button from "components/common/Button" | ||
import { ArrowLeft, Info } from "phosphor-react" | ||
import SelectRoleOrSetRequirements from "platforms/components/SelectRoleOrSetRequirements" | ||
import rewards, { CAPACITY_TIME_PLATFORMS } from "platforms/rewards" | ||
import { useState } from "react" | ||
import { useFormContext, useWatch } from "react-hook-form" | ||
import { RoleTypeToAddTo, useAddRewardContext } from "../AddRewardContext" | ||
import { defaultValues } from "./AddRewardButton" | ||
import AvailabilitySetup from "./components/AvailabilitySetup" | ||
import useSubmitAddReward from "./hooks/useSubmitAddReward" | ||
|
||
const SelectRolePanel = () => { | ||
const { modalRef, selection, activeTab, setStep, isBackButtonDisabled } = | ||
useAddRewardContext() | ||
|
||
const { onSubmit, isLoading } = useSubmitAddReward() | ||
|
||
const lightModalBgColor = useColorModeValue("white", "gray.700") | ||
|
||
const methods = useFormContext() | ||
const rolePlatform = methods.getValues("rolePlatforms.0") | ||
|
||
const requirements = useWatch({ name: "requirements", control: methods.control }) | ||
const roleIds = useWatch({ name: "roleIds", control: methods.control }) | ||
|
||
const [saveAsDraft, setSaveAsDraft] = useState(false) | ||
|
||
const isRoleSelectorDisabled = selection === "ERC20" | ||
const isAddRewardButtonDisabled = | ||
activeTab === RoleTypeToAddTo.NEW_ROLE || isRoleSelectorDisabled | ||
? !requirements?.length | ||
: !roleIds?.length | ||
|
||
const { RewardPreview } = rewards[selection] ?? {} | ||
|
||
const goBack = () => { | ||
if (!rewards[selection].autoRewardSetup) methods.reset(defaultValues) | ||
setStep("HOME") | ||
} | ||
|
||
return ( | ||
<ModalContent> | ||
<ModalCloseButton /> | ||
<ModalHeader bgColor={lightModalBgColor} boxShadow={"sm"} zIndex={1}> | ||
<Stack spacing={8}> | ||
<HStack> | ||
<IconButton | ||
isDisabled={isBackButtonDisabled} | ||
rounded="full" | ||
aria-label="Back" | ||
size="sm" | ||
mb="-3px" | ||
icon={<ArrowLeft size={20} />} | ||
variant="ghost" | ||
onClick={goBack} | ||
/> | ||
<Text>{`Add ${rewards[selection].name} reward`}</Text> | ||
</HStack> | ||
|
||
<RewardPreview> | ||
{CAPACITY_TIME_PLATFORMS.includes(selection) && ( | ||
<AvailabilitySetup | ||
platformType={rolePlatform?.guildPlatform?.platformName} | ||
rolePlatform={rolePlatform} | ||
defaultValues={{ | ||
/** | ||
* If the user doesn't upload mint links for a POAP, we should | ||
* fallback to undefined, since 0 is not a valid value here | ||
*/ | ||
capacity: | ||
rolePlatform?.guildPlatform?.platformGuildData?.texts?.length || | ||
undefined, | ||
/** POAPs have default startTime and endTime */ | ||
startTime: rolePlatform?.startTime, | ||
endTime: rolePlatform?.endTime, | ||
}} | ||
onDone={({ capacity, startTime, endTime }) => { | ||
methods.setValue(`rolePlatforms.0.capacity`, capacity) | ||
methods.setValue(`rolePlatforms.0.startTime`, startTime) | ||
methods.setValue(`rolePlatforms.0.endTime`, endTime) | ||
}} | ||
/> | ||
)} | ||
</RewardPreview> | ||
</Stack> | ||
</ModalHeader> | ||
|
||
<ModalBody | ||
ref={modalRef} | ||
className="custom-scrollbar" | ||
display="flex" | ||
flexDir="column" | ||
> | ||
<SelectRoleOrSetRequirements | ||
selectedPlatform={selection} | ||
isRoleSelectorDisabled={isRoleSelectorDisabled} | ||
/> | ||
</ModalBody> | ||
|
||
<ModalFooter pt="6" pb="8" gap={2}> | ||
<Button | ||
isDisabled={isAddRewardButtonDisabled} | ||
onClick={methods.handleSubmit((data) => { | ||
setSaveAsDraft(true) | ||
onSubmit(data, "DRAFT") | ||
})} | ||
isLoading={saveAsDraft && isLoading} | ||
rightIcon={ | ||
<Tooltip | ||
label={ | ||
activeTab === RoleTypeToAddTo.EXISTING_ROLE | ||
? "The reward will be added to the role you select with hidden visibility, so users won't see it yet. You can edit & activate it later" | ||
: "The role will be created with hidden visibility, so users won't see it yet. You can edit & activate it later" | ||
} | ||
> | ||
<Info /> | ||
</Tooltip> | ||
} | ||
> | ||
Save as draft | ||
</Button> | ||
<Button | ||
isDisabled={isAddRewardButtonDisabled} | ||
colorScheme="green" | ||
onClick={methods.handleSubmit((data) => { | ||
setSaveAsDraft(false) | ||
onSubmit(data) | ||
})} | ||
isLoading={!saveAsDraft && isLoading} | ||
> | ||
Save | ||
</Button> | ||
</ModalFooter> | ||
</ModalContent> | ||
) | ||
} | ||
|
||
export default SelectRolePanel |
135 changes: 135 additions & 0 deletions
135
src/components/[guild]/AddRewardButton/hooks/useSubmitAddReward.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
import { useAddRewardContext } from "components/[guild]/AddRewardContext" | ||
import useGuild from "components/[guild]/hooks/useGuild" | ||
import { usePostHogContext } from "components/_app/PostHogProvider" | ||
import useCreateRole from "components/create-guild/hooks/useCreateRole" | ||
import useToast from "hooks/useToast" | ||
import rewards from "platforms/rewards" | ||
import { useFormContext } from "react-hook-form" | ||
import { PlatformType, Visibility } from "types" | ||
import getRandomInt from "utils/getRandomInt" | ||
import { defaultValues } from "../AddRewardButton" | ||
import useCreateReqBasedTokenReward from "../useCreateTokenReward" | ||
import useAddReward from "./useAddReward" | ||
import { useAddRewardDiscardAlert } from "./useAddRewardDiscardAlert" | ||
|
||
const isERC20 = (data) => | ||
data.rolePlatforms[0].guildPlatform.platformId === PlatformType.ERC20 | ||
|
||
const useSubmitAddReward = () => { | ||
const toast = useToast() | ||
const { selection, onClose: onAddRewardModalClose } = useAddRewardContext() | ||
const [, setIsAddRewardPanelDirty] = useAddRewardDiscardAlert() | ||
const { roles } = useGuild() | ||
const { captureEvent } = usePostHogContext() | ||
|
||
const methods = useFormContext() | ||
|
||
const onCloseAndClear = () => { | ||
methods.reset(defaultValues) | ||
onAddRewardModalClose() | ||
setIsAddRewardPanelDirty(false) | ||
} | ||
|
||
const { onSubmit: onCreateRoleSubmit, isLoading: isCreateRoleLoading } = | ||
useCreateRole({ | ||
onSuccess: () => { | ||
toast({ status: "success", title: "Reward successfully added" }) | ||
onCloseAndClear() | ||
}, | ||
}) | ||
|
||
const { submitCreate: submitCreateReqBased, isLoading: erc20Loading } = | ||
useCreateReqBasedTokenReward({ | ||
onSuccess: () => { | ||
toast({ status: "success", title: "Reward successfully added" }) | ||
onCloseAndClear() | ||
}, | ||
onError: (err) => console.error(err), | ||
}) | ||
|
||
const { onSubmit: onAddRewardSubmit, isLoading: isAddRewardLoading } = | ||
useAddReward({ | ||
onSuccess: () => { | ||
captureEvent("[discord setup] successfully added to existing guild") | ||
onCloseAndClear() | ||
}, | ||
onError: (err) => { | ||
captureEvent("[discord setup] failed to add to existing guild", { | ||
error: err, | ||
}) | ||
}, | ||
}) | ||
|
||
const isLoading = isAddRewardLoading || isCreateRoleLoading || erc20Loading | ||
|
||
const submitERC20Reward = async ( | ||
data: any, | ||
saveAs: "DRAFT" | "PUBLIC" = "PUBLIC" | ||
) => { | ||
const isRequirementBased = | ||
data.rolePlatforms[0].dynamicAmount.operation.input.type === | ||
"REQUIREMENT_AMOUNT" | ||
|
||
const guildPlatformExists = !!data.rolePlatforms[0].guildPlatformId | ||
|
||
if (isRequirementBased) { | ||
submitCreateReqBased(data, saveAs) | ||
return | ||
} else { | ||
/** TODO: Write when static reward is needed */ | ||
if (guildPlatformExists) { | ||
data.rolePlatforms[0].guildPlatform = { | ||
platformId: PlatformType.ERC20, | ||
platformName: "ERC20", | ||
platformGuildId: "", | ||
platformGuildData: {}, | ||
} | ||
} | ||
return | ||
} | ||
} | ||
|
||
const onSubmit = async (data: any, saveAs: "DRAFT" | "PUBLIC" = "PUBLIC") => { | ||
if (isERC20(data)) return submitERC20Reward(data, saveAs) | ||
|
||
if (data.requirements?.length > 0) { | ||
const roleVisibility = | ||
saveAs === "DRAFT" ? Visibility.HIDDEN : Visibility.PUBLIC | ||
onCreateRoleSubmit({ | ||
...data, | ||
name: data.name || `New ${rewards[selection].name} role`, | ||
imageUrl: data.imageUrl || `/guildLogos/${getRandomInt(286)}.svg`, | ||
roleVisibility, | ||
rolePlatforms: data.rolePlatforms.map((rp) => ({ | ||
...rp, | ||
visibility: roleVisibility, | ||
})), | ||
}) | ||
} else { | ||
onAddRewardSubmit({ | ||
...data.rolePlatforms[0].guildPlatform, | ||
rolePlatforms: data.roleIds | ||
?.filter((roleId) => !!roleId) | ||
.map((roleId) => ({ | ||
// We'll be able to send additional params here, like capacity & time | ||
roleId: +roleId, | ||
/** | ||
* Temporary for POINTS rewards, because they can be added to | ||
* multiple roles and this field has a unique constraint in | ||
* the DB | ||
*/ | ||
platformRoleId: roleId, | ||
...data.rolePlatforms[0], | ||
visibility: | ||
saveAs === "DRAFT" | ||
? Visibility.HIDDEN | ||
: roles.find((role) => role.id === +roleId).visibility, | ||
})), | ||
}) | ||
} | ||
} | ||
|
||
return { onSubmit, isLoading } | ||
} | ||
|
||
export default useSubmitAddReward |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.