Skip to content
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { zodResolver } from "@hookform/resolvers/zod";
import { useQueryClient } from "@tanstack/react-query";
import { useState } from "react";
import { useFieldArray, useForm } from "react-hook-form";
import { View } from "react-native";

import { RolesMembersSettingsSection } from "./RolesMembersSettingsSection";
Expand All @@ -25,8 +27,10 @@ import {
CreateDaoFormType,
LAUNCHING_PROCESS_STEPS,
ROLES_BASED_ORGANIZATION_STEPS,
RolesMemberSettingFormType,
RolesSettingFormType,
RolesFormType,
RolesMembersFormType,
ZodRolesMembersObject,
ZodRolesObject,
} from "@/utils/types/organizations";

export const RolesDeployerSteps: React.FC<{
Expand All @@ -49,33 +53,60 @@ export const RolesDeployerSteps: React.FC<{
const network = getNetwork(selectedWallet?.networkId);
const queryClient = useQueryClient();
const { setToast } = useFeedbacks();
const rolesMembersForm = useForm<RolesMembersFormType>({
resolver: zodResolver(ZodRolesMembersObject),
defaultValues: {
members: selectedWallet?.address
? [
{
addr: selectedWallet?.address,
weight: "0",
roles: "",
},
]
: [],
},
});
const rolesForm = useForm<RolesFormType>({
resolver: zodResolver(ZodRolesObject),
defaultValues: {
roles: [],
},
});
const membersField = useFieldArray({
control: rolesMembersForm.control,
name: "members",
});
const rolesField = useFieldArray({
control: rolesForm.control,
name: "roles",
});

const [configureVotingFormData, setConfigureVotingFormData] =
useState<ConfigureVotingFormType>();
const [rolesSettingsFormData, setRolesSettingsFormData] =
useState<RolesSettingFormType>();
const [memberSettingsFormData, setMemberSettingsFormData] =
useState<RolesMemberSettingFormType>();
// const [rolesSettingsFormData, setRolesSettingsFormData] =
// useState<RolesSettingFormType>();
// const [memberSettingsFormData, setMemberSettingsFormData] =
// useState<RolesMemberSettingFormType>();

const createDaoContract = async (): Promise<boolean> => {
try {
switch (network?.kind) {
case NetworkKind.Gno: {
const name = organizationData?.associatedHandle!;
const roles =
rolesSettingsFormData?.roles?.map((role) => ({
rolesField?.fields?.map((role) => ({
name: role.name.trim(),
color: role.color,
resources: role.resources,
resources: role.resources || [],
})) || [];
const initialMembers = (memberSettingsFormData?.members || []).map(
(member) => ({
address: member.addr,
weight: parseInt(member.weight, 10),
roles: member.roles
? member.roles.split(",").map((role) => role.trim())
: [],
}),
);
const initialMembers = (membersField?.fields || []).map((member) => ({
address: member.addr,
weight: parseInt(member.weight, 10),
roles: member.roles
? member.roles.split(",").map((role) => role.trim())
: [],
}));
const pkgPath = await adenaDeployGnoDAO(
network.id,
selectedWallet?.address!,
Expand Down Expand Up @@ -113,7 +144,7 @@ export const RolesDeployerSteps: React.FC<{
network.cwAdminFactoryContractAddress!;
const walletAddress = selectedWallet.address;

if (!memberSettingsFormData) return false;
if (!membersField.fields) return false;
const params: CreateDaoMemberBasedParams = {
networkId,
sender: walletAddress,
Expand All @@ -127,7 +158,7 @@ export const RolesDeployerSteps: React.FC<{
description: organizationData.organizationDescription,
tns: organizationData.associatedHandle,
imageUrl: organizationData.imageUrl,
members: memberSettingsFormData.members.map((value) => ({
members: membersField.fields.map((value) => ({
addr: value.addr,
weight: parseInt(value.weight, 10),
})),
Expand Down Expand Up @@ -184,13 +215,11 @@ export const RolesDeployerSteps: React.FC<{
setCurrentStep(2);
};

const onSubmitRolesSettings = (data: RolesSettingFormType) => {
setRolesSettingsFormData(data);
const onSubmitRolesSettings = () => {
setCurrentStep(3);
};

const onSubmitMemberSettings = (data: RolesMemberSettingFormType) => {
setMemberSettingsFormData(data);
const onSubmitMemberSettings = () => {
setCurrentStep(4);
};

Expand All @@ -215,8 +244,6 @@ export const RolesDeployerSteps: React.FC<{
);
setOrganizationData(undefined);
setConfigureVotingFormData(undefined);
setRolesSettingsFormData(undefined);
setMemberSettingsFormData(undefined);
setCurrentStep(0);
setDAOAddress("");
setLaunchingStep(0);
Expand All @@ -239,14 +266,25 @@ export const RolesDeployerSteps: React.FC<{
currentStep === 2 ? { display: "flex", flex: 1 } : { display: "none" }
}
>
<RolesSettingsSection onSubmit={onSubmitRolesSettings} />
<RolesSettingsSection
remove={rolesField.remove}
append={rolesField.append}
roles={rolesField.fields}
handleSubmit={rolesForm.handleSubmit(onSubmitRolesSettings)}
/>
</View>
<View
style={
currentStep === 3 ? { display: "flex", flex: 1 } : { display: "none" }
}
>
<RolesMembersSettingsSection onSubmit={onSubmitMemberSettings} />
<RolesMembersSettingsSection
members={membersField.fields}
append={membersField.append}
control={rolesMembersForm.control}
remove={membersField.remove}
handleSubmit={rolesMembersForm.handleSubmit(onSubmitMemberSettings)}
/>
</View>
<View
style={
Expand All @@ -256,8 +294,8 @@ export const RolesDeployerSteps: React.FC<{
<RolesReviewInformationSection
organizationData={organizationData}
votingSettingData={configureVotingFormData}
rolesSettingData={rolesSettingsFormData}
memberSettingData={memberSettingsFormData}
rolesSettingData={rolesField.fields}
memberSettingData={membersField.fields}
onSubmit={onStartLaunchingProcess}
/>
</View>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import React, { useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import React from "react";
import { Control, UseFieldArrayAppend } from "react-hook-form";
import { Pressable, ScrollView, View, ViewStyle } from "react-native";
import { z } from "zod";

import trashSVG from "../../../../../assets/icons/trash.svg";
import walletInputSVG from "../../../../../assets/icons/wallet-input.svg";
import useSelectedWallet from "../../../../hooks/useSelectedWallet";

import { BrandText } from "@/components/BrandText";
import { SVG } from "@/components/SVG";
Expand All @@ -18,50 +18,31 @@ import { fontSemibold28 } from "@/utils/style/fonts";
import { layout } from "@/utils/style/layout";
import {
ROLES_BASED_ORGANIZATION_STEPS,
RolesMemberSettingFormType,
RolesMembersFormType,
ZodRolesMemberObject,
} from "@/utils/types/organizations";

interface RolesMembersSettingsSectionProps {
onSubmit: (form: RolesMemberSettingFormType) => void;
members: z.infer<typeof ZodRolesMemberObject>[];
append: UseFieldArrayAppend<RolesMembersFormType>;
control: Control<RolesMembersFormType>;
remove: (index?: number | number[] | undefined) => void;
handleSubmit: () => void;
}

export const RolesMembersSettingsSection: React.FC<
RolesMembersSettingsSectionProps
> = ({ onSubmit }) => {
const { handleSubmit, control, resetField, unregister } =
useForm<RolesMemberSettingFormType>();

// this effect put the selected wallet address in the first field only on initial load
const selectedWallet = useSelectedWallet();
const [initialReset, setInitialReset] = useState(false);
useEffect(() => {
if (initialReset) {
return;
}
if (!selectedWallet?.address) {
return;
}
resetField("members.0.addr", {
defaultValue: selectedWallet?.address,
});
setInitialReset(true);
}, [selectedWallet?.address, resetField, initialReset]);

const [addressIndexes, setAddressIndexes] = useState<number[]>([0]);

// functions
const removeAddressField = (id: number, index: number) => {
unregister(`members.${index}.addr`);
unregister(`members.${index}.weight`);
unregister(`members.${index}.roles`);
if (addressIndexes.length > 1) {
const copyIndex = [...addressIndexes].filter((i) => i !== id);
setAddressIndexes(copyIndex);
}
> = ({ handleSubmit, append, remove, members, control }) => {
const removeAddressField = (index: number) => {
remove(index);
};

const addAddressField = () => {
setAddressIndexes([...addressIndexes, Math.floor(Math.random() * 200000)]);
append({
addr: "",
weight: "",
roles: "",
});
};

return (
Expand All @@ -70,10 +51,10 @@ export const RolesMembersSettingsSection: React.FC<
<BrandText style={fontSemibold28}>Members</BrandText>
<SpacerColumn size={2.5} />

{addressIndexes.map((id, index) => (
<View style={inputContainerCStyle} key={id.toString()}>
{members.map((member, index) => (
<View style={inputContainerCStyle} key={member.addr}>
<View style={leftInputCStyle}>
<TextInputCustom<RolesMemberSettingFormType>
<TextInputCustom<RolesMembersFormType>
name={`members.${index}.addr`}
noBrokenCorners
label="Member Address"
Expand All @@ -85,15 +66,15 @@ export const RolesMembersSettingsSection: React.FC<
>
<Pressable
style={trashContainerCStyle}
onPress={() => removeAddressField(id, index)}
onPress={() => removeAddressField(index)}
>
<SVG source={trashSVG} width={12} height={12} />
</Pressable>
</TextInputCustom>
</View>
<SpacerRow size={2.5} />
<View style={rightInputCStyle}>
<TextInputCustom<RolesMemberSettingFormType>
<TextInputCustom<RolesMembersFormType>
name={`members.${index}.weight`}
noBrokenCorners
label="Weight"
Expand All @@ -106,7 +87,7 @@ export const RolesMembersSettingsSection: React.FC<
</View>
<SpacerRow size={2.5} />
<View style={rightInputCStyle}>
<TextInputCustom<RolesMemberSettingFormType>
<TextInputCustom<RolesMembersFormType>
name={`members.${index}.roles`}
noBrokenCorners
label="Roles - separate with a comma"
Expand All @@ -125,7 +106,7 @@ export const RolesMembersSettingsSection: React.FC<
<PrimaryButton
size="M"
text={`Next: ${ROLES_BASED_ORGANIZATION_STEPS[4]}`}
onPress={handleSubmit(onSubmit)}
onPress={handleSubmit}
testID="member-settings-next"
/>
</View>
Expand Down
Loading
Loading