Skip to content

Instantly share code, notes, and snippets.

@AlexandroMtzG
Created January 31, 2023 01:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AlexandroMtzG/af55cf065b187e6ae4657ccde32202ab to your computer and use it in GitHub Desktop.
Save AlexandroMtzG/af55cf065b187e6ae4657ccde32202ab to your computer and use it in GitHub Desktop.
import { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { Colors } from "~/application/enums/shared/Colors";
import ButtonTertiary from "~/components/ui/buttons/ButtonTertiary";
import InputSelector from "~/components/ui/input/InputSelector";
import CollapsibleRow from "~/components/ui/tables/CollapsibleRow";
import { useAppData } from "~/utils/data/useAppData";
import { TenantUserWithDetails } from "~/utils/db/tenants.db.server";
import { SignerDto } from "../dtos/SignerDto";
export default function ContractSignersForm({
possibleSigners,
items,
onChange,
}: {
possibleSigners: TenantUserWithDetails[];
items?: SignerDto[];
onChange?: (e: SignerDto[]) => void;
}) {
const appData = useAppData();
const [signers, setSigners] = useState<SignerDto[]>(items ?? []);
useEffect(() => {
const currentUser = possibleSigners.find((s) => s.userId === appData.user.id && s.tenantId === appData.currentTenant.id);
if (currentUser) {
setSigners([
{
id: currentUser.id,
tenant: {
id: currentUser.tenantId,
name: currentUser.tenant.name,
},
user: {
id: currentUser.userId,
email: currentUser.user.email,
name: currentUser.user.firstName + " " + currentUser.user.lastName,
},
role: "signer",
signedAt: null,
},
]);
}
}, [appData, possibleSigners]);
useEffect(() => {
if (onChange) {
onChange(signers);
}
}, [onChange, signers]);
return (
<div className="flex flex-col space-y-2">
{signers.length === 0 && (
<div className="flex justify-center rounded-md border-2 border-dashed border-gray-300 bg-white p-3">
<div className="text-sm italic text-gray-500">No signers</div>
</div>
)}
{signers.map((item, idx) => {
return <input key={idx} readOnly hidden type="text" id="signers[]" name="signers[]" value={JSON.stringify(item)} />;
})}
{signers.map((item, idx) => (
<CollapsibleRow
key={idx}
title={item.user.email || "Signer #" + (idx + 1)}
value={item.user.email ? `${item.user.email} (${item.role})` : "Signer #" + (idx + 1)}
initial={!item.user.email}
onRemove={() => {
setSigners(signers.filter((_, i) => i !== idx));
}}
>
<SignerAccountEmailAndName
item={item}
onChange={(e) => setSigners(signers.map((s, i) => (i === idx ? { ...s, ...e } : s)))}
possibleSigners={possibleSigners}
/>
</CollapsibleRow>
))}
<ButtonTertiary
onClick={() =>
setSigners([
...signers,
{
user: { id: "", email: "", name: "" },
tenant: { id: "", name: "" },
role: "signer",
signedAt: null,
},
])
}
>
<div>Add signer</div>
</ButtonTertiary>
</div>
);
}
function SignerAccountEmailAndName({
possibleSigners,
item,
onChange,
}: {
possibleSigners: TenantUserWithDetails[];
item: SignerDto;
onChange: (e: SignerDto) => void;
}) {
const { t } = useTranslation();
return (
<div className="grid grid-cols-3 gap-2">
<InputSelector
className="col-span-2"
title={t("models.user.object")}
value={item.user.id}
withSearch={true}
withColors={false}
options={possibleSigners.map((s) => ({
value: s.userId,
name: `${s.user.email} (${s.tenant.name})`,
}))}
setValue={(e) => {
const selected = possibleSigners.find((s) => s.userId === e);
if (selected) {
onChange({
...item,
user: {
id: selected.userId,
email: selected.user.email,
name: selected.user.firstName + " " + selected.user.lastName,
},
tenant: {
id: selected.tenantId,
name: selected.tenant.name,
},
});
}
}}
/>
<InputSelector
title="Role"
value={item.role}
setValue={(e) => {
onChange({ ...item, role: e?.toString() ?? "signer" });
}}
options={[
{
name: "Signer",
value: "signer",
color: Colors.GREEN,
},
{
name: "Viewer",
value: "viewer",
color: Colors.GRAY,
},
]}
withSearch={false}
withColors={true}
/>
</div>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment