Skip to content

Commit

Permalink
Lock expense payer and remove "Who is paying?" when submitting invite…
Browse files Browse the repository at this point in the history
… and coming from a Collective page
  • Loading branch information
gustavlrsn committed Feb 27, 2025
1 parent 9fa19da commit 3801674
Show file tree
Hide file tree
Showing 26 changed files with 86 additions and 23 deletions.
10 changes: 10 additions & 0 deletions components/AccountHoverCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,16 @@ export const accountHoverCardFields = gql`
}
`;

export const accountHoverCardQuery = gql`
query Account($slug: String!) {
account(slug: $slug) {
id
...AccountHoverCardFields
}
}
${accountHoverCardFields}
`;

type AccountHoverCardProps = {
trigger: React.ReactNode;
account: {
Expand Down
14 changes: 2 additions & 12 deletions components/dashboard/filters/HostedAccountFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,11 @@ import { API_V2_CONTEXT, gql } from '../../../lib/graphql/helpers';
import type { AccountHoverCardFieldsFragment, AccountQuery } from '../../../lib/graphql/types/v2/graphql';
import type { Account } from '../../../lib/graphql/types/v2/schema';

import { AccountHoverCard, accountHoverCardFields } from '../../AccountHoverCard';
import { AccountHoverCard, accountHoverCardFields, accountHoverCardQuery } from '../../AccountHoverCard';
import Avatar from '../../Avatar';

import ComboSelectFilter from './ComboSelectFilter';

const accountQuery = gql`
query Account($slug: String!) {
account(slug: $slug) {
id
...AccountHoverCardFields
}
}
${accountHoverCardFields}
`;

const hostedAccountFilterSearchQuery = gql`
query HostedAccountFilterSearch($searchTerm: String, $hostSlug: String, $orderBy: OrderByInput) {
accounts(searchTerm: $searchTerm, host: { slug: $hostSlug }, orderBy: $orderBy) {
Expand All @@ -44,7 +34,7 @@ export const AccountRenderer = ({
};
inOptionsList?: boolean; // For positioning the HoverCard to the right to prevent blocking options list
}) => {
const { data } = useQuery<AccountQuery>(accountQuery, {
const { data } = useQuery<AccountQuery>(accountHoverCardQuery, {
variables: { slug: account.slug },
fetchPolicy: 'cache-first',
context: API_V2_CONTEXT,
Expand Down
44 changes: 39 additions & 5 deletions components/submit-expense/SubmitExpenseFlow.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import type { FetchResult } from '@apollo/client';
import { gql, useMutation } from '@apollo/client';
import { gql, useMutation, useQuery } from '@apollo/client';
import dayjs from 'dayjs';
import { FormikProvider } from 'formik';
import { pick } from 'lodash';
Expand All @@ -13,6 +13,7 @@ import { CollectiveType } from '../../lib/constants/collectives';
import { i18nGraphqlException } from '../../lib/errors';
import { API_V2_CONTEXT } from '../../lib/graphql/helpers';
import type {
AccountQuery,
CreateExpenseFromDashboardMutation,
CreateExpenseFromDashboardMutationVariables,
CurrencyExchangeRateInput,
Expand All @@ -21,10 +22,12 @@ import type {
InviteExpenseFromDashboardMutation,
InviteExpenseFromDashboardMutationVariables,
} from '../../lib/graphql/types/v2/graphql';
import type { Currency, RecurringExpenseInterval } from '../../lib/graphql/types/v2/schema';
import type { Account, Currency, RecurringExpenseInterval } from '../../lib/graphql/types/v2/schema';
import { ExpenseStatus, ExpenseType, PayoutMethodType } from '../../lib/graphql/types/v2/schema';
import useLoggedInUser from '../../lib/hooks/useLoggedInUser';

import { AccountHoverCard, accountHoverCardQuery } from '../AccountHoverCard';
import Avatar from '../Avatar';
import { Survey, SURVEY_KEY } from '../Survey';
import { Button } from '../ui/Button';
import { Dialog, DialogContent, DialogFooter } from '../ui/Dialog';
Expand Down Expand Up @@ -419,9 +422,17 @@ export function SubmitExpenseFlow(props: SubmitExpenseFlowProps) {
>
<div className="flex max-h-screen min-h-screen max-w-screen min-w-screen flex-col overflow-hidden bg-[#F8FAFC]">
<header className="flex min-w-screen items-center justify-between border-b border-slate-100 px-4 py-3 sm:px-10">
<span className="text-xl leading-7 font-bold text-slate-800">
<FormattedMessage id="ExpenseForm.Submit" defaultMessage="Submit expense" />
</span>
<div className="flex grow items-center gap-2 text-xl leading-7 font-semibold">
{props.submitExpenseTo ? (
<FormattedMessage
id="ExpenseForm.SubmitTo"
defaultMessage="Submit expense to {account}"
values={{ account: <AccountRenderer accountSlug={props.submitExpenseTo} /> }}
/>
) : (
<FormattedMessage id="ExpenseForm.Submit" defaultMessage="Submit expense" />
)}
</div>
<Button
disabled={isLoading}
loading={isLoading}
Expand Down Expand Up @@ -466,6 +477,28 @@ export function SubmitExpenseFlow(props: SubmitExpenseFlowProps) {
);
}

const AccountRenderer = ({ accountSlug }: { accountSlug: Account['slug'] }) => {
const { data } = useQuery<AccountQuery>(accountHoverCardQuery, {
variables: { slug: accountSlug },
fetchPolicy: 'cache-first',
context: API_V2_CONTEXT,
});

return (
<AccountHoverCard
account={data.account}
trigger={
<div className="inline-flex h-full w-full max-w-48 items-center justify-between gap-2 overflow-hidden">
<Avatar collective={data.account} radius={20} />
<div className="relative flex flex-1 items-center justify-between gap-1 overflow-hidden">
<span className="truncate">{data.account?.name ?? accountSlug}</span>
</div>
</div>
}
/>
);
};

function ExpenseFormikContainer(props: {
submitExpenseTo?: string;
draftKey?: string;
Expand All @@ -480,6 +513,7 @@ function ExpenseFormikContainer(props: {
draftKey: props.draftKey,
duplicateExpense: props.duplicateExpense,
expenseId: props.expenseId,
canChangeAccount: !props.submitExpenseTo,
});

const [activeStep, setActiveStep] = React.useState(Step.WHO_IS_PAYING);
Expand Down
3 changes: 3 additions & 0 deletions components/submit-expense/SubmitExpenseFlowSteps.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,9 @@ export function SubmitExpenseFlowSteps(props: SubmitExpenseFlowStepsProps) {
if (step === Step.EXPENSE_CATEGORY) {
return form.options.isAccountingCategoryRequired && form.options.accountingCategories?.length;
}
if (step === Step.WHO_IS_PAYING) {
return form.options.canChangeAccount;
}

return true;
});
Expand Down
4 changes: 3 additions & 1 deletion components/submit-expense/form/SubmitExpenseFlowForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ export function SubmitExpenseFlowForm(props: SubmitExpenseFlowFormProps) {
onExpenseInviteDeclined={props.onExpenseInviteDeclined}
/>
)}
<WhoIsPayingSection inViewChange={onInViewChange} {...WhoIsPayingSection.getFormProps(form)} />
{form.options.canChangeAccount && (
<WhoIsPayingSection inViewChange={onInViewChange} {...WhoIsPayingSection.getFormProps(form)} />
)}
<WhoIsGettingPaidSection inViewChange={onInViewChange} {...WhoIsGettingPaidSection.getFormProps(form)} />
<PayoutMethodSection inViewChange={onInViewChange} {...PayoutMethodSection.getFormProps(form)} />
<TypeOfExpenseSection inViewChange={onInViewChange} {...TypeOfExpenseSection.getFormProps(form)} />
Expand Down
2 changes: 1 addition & 1 deletion components/submit-expense/form/WhoIsPayingSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { memoWithGetFormProps } from './helper';

type WhoIsPayingSectionProps = {
inViewChange: (inView: boolean, entry: IntersectionObserverEntry) => void;
lockPayee?: boolean;
} & ReturnType<typeof getFormProps>;

function getFormProps(form: ExpenseForm) {
Expand All @@ -36,7 +37,6 @@ export const WhoIsPayingSection = memoWithGetFormProps(function WhoIsPayingSecti
const [isLoading, setIsLoading] = React.useState(true);
const lastSubmittedExpense = props.recentlySubmittedExpenses?.nodes?.at?.(0);
const lastSubmittedAccount = lastSubmittedExpense && lastSubmittedExpense.account;

const recentlySubmittedAccounts = React.useMemo(
() => uniqBy((props.recentlySubmittedExpenses?.nodes || []).map(e => e?.account).filter(Boolean), 'slug'),
[props.recentlySubmittedExpenses],
Expand Down
13 changes: 9 additions & 4 deletions components/submit-expense/useExpenseForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import dayjs from 'dayjs';
import type { Path, PathValue } from 'dot-path-value';
import type { FieldInputProps, FormikErrors, FormikHelpers } from 'formik';
import { useFormik } from 'formik';
import { isEmpty, isEqual, isNull, omit, pick, set, uniqBy } from 'lodash';
import { isEmpty, isEqual, isNull, isUndefined, omit, pick, set, uniqBy } from 'lodash';
import memoizeOne from 'memoize-one';
import type { IntlShape } from 'react-intl';
import { useIntl } from 'react-intl';
Expand Down Expand Up @@ -1272,10 +1272,14 @@ async function buildFormOptions(
const payeeHost = payee && 'host' in payee ? payee.host : null;
const submitter = options.expense?.submitter || query.data?.submitter;

if (account && options.expense?.status === ExpenseStatus.DRAFT) {
options.canChangeAccount = false;
if (isUndefined(startOptions.canChangeAccount)) {
if (account && options.expense?.status === ExpenseStatus.DRAFT) {
options.canChangeAccount = false;
} else {
options.canChangeAccount = true;
}
} else {
options.canChangeAccount = true;
options.canChangeAccount = startOptions.canChangeAccount;
}

if (recentlySubmittedExpenses) {
Expand Down Expand Up @@ -1450,6 +1454,7 @@ type ExpenseFormStartOptions = {
draftKey?: string;
isInlineEdit?: boolean;
pickSchemaFields?: Record<string, boolean>;
canChangeAccount?: boolean;
};

export function useExpenseForm(opts: {
Expand Down
1 change: 1 addition & 0 deletions lang/ca.json
Original file line number Diff line number Diff line change
Expand Up @@ -1534,6 +1534,7 @@
"ExpenseForm.StepPayeeInvoice": "Payee information",
"ExpenseForm.Submit": "Submit expense",
"ExpenseForm.SubmitRequest": "Envia la sol·licitud",
"ExpenseForm.SubmitTo": "Submit expense to {account}",
"ExpenseForm.Type.Request": "Request Grant",
"ExpenseFormPayeeStep.PrivateInfo": "This information is private",
"ExpenseFormPayeeStep.PrivateInfoDetails": "The payout method details are private and can only be viewed by the Payee and the Host admins.",
Expand Down
1 change: 1 addition & 0 deletions lang/cs.json
Original file line number Diff line number Diff line change
Expand Up @@ -1534,6 +1534,7 @@
"ExpenseForm.StepPayeeInvoice": "Payee information",
"ExpenseForm.Submit": "Odeslat výdaj",
"ExpenseForm.SubmitRequest": "Odeslat žádost",
"ExpenseForm.SubmitTo": "Submit expense to {account}",
"ExpenseForm.Type.Request": "Request Grant",
"ExpenseFormPayeeStep.PrivateInfo": "This information is private",
"ExpenseFormPayeeStep.PrivateInfoDetails": "The payout method details are private and can only be viewed by the Payee and the Host admins.",
Expand Down
1 change: 1 addition & 0 deletions lang/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -1534,6 +1534,7 @@
"ExpenseForm.StepPayeeInvoice": "Angaben zum Zahlungsempfänger",
"ExpenseForm.Submit": "Ausgaben einreichen",
"ExpenseForm.SubmitRequest": "Anfrage absenden",
"ExpenseForm.SubmitTo": "Submit expense to {account}",
"ExpenseForm.Type.Request": "Zuwendung anfordern",
"ExpenseFormPayeeStep.PrivateInfo": "This information is private",
"ExpenseFormPayeeStep.PrivateInfoDetails": "The payout method details are private and can only be viewed by the Payee and the Host admins.",
Expand Down
1 change: 1 addition & 0 deletions lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1534,6 +1534,7 @@
"ExpenseForm.StepPayeeInvoice": "Payee information",
"ExpenseForm.Submit": "Submit expense",
"ExpenseForm.SubmitRequest": "Submit request",
"ExpenseForm.SubmitTo": "Submit expense to {account}",
"ExpenseForm.Type.Request": "Request Grant",
"ExpenseFormPayeeStep.PrivateInfo": "This information is private",
"ExpenseFormPayeeStep.PrivateInfoDetails": "The payout method details are private and can only be viewed by the Payee and the Host admins.",
Expand Down
1 change: 1 addition & 0 deletions lang/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -1534,6 +1534,7 @@
"ExpenseForm.StepPayeeInvoice": "Información del beneficiario",
"ExpenseForm.Submit": "Enviar gasto",
"ExpenseForm.SubmitRequest": "Enviar solicitud",
"ExpenseForm.SubmitTo": "Submit expense to {account}",
"ExpenseForm.Type.Request": "Solicitar Subvención",
"ExpenseFormPayeeStep.PrivateInfo": "Esta información es privada",
"ExpenseFormPayeeStep.PrivateInfoDetails": "Los detalles de los métodos de pago son privados y solo pueden ser visualizados por el beneficiario y los administradores anfitriones.",
Expand Down
1 change: 1 addition & 0 deletions lang/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -1534,6 +1534,7 @@
"ExpenseForm.StepPayeeInvoice": "Informations sur le bénéficiaire",
"ExpenseForm.Submit": "Envoyer une dépense",
"ExpenseForm.SubmitRequest": "Soumettre une requête",
"ExpenseForm.SubmitTo": "Submit expense to {account}",
"ExpenseForm.Type.Request": "Demande de subvention",
"ExpenseFormPayeeStep.PrivateInfo": "Cette information est privée",
"ExpenseFormPayeeStep.PrivateInfoDetails": "Les détails de la méthode de paiement sont privés et ne peuvent être consultés que par le bénéficiaire et les administrateurs de l'hôte.",
Expand Down
1 change: 1 addition & 0 deletions lang/he.json
Original file line number Diff line number Diff line change
Expand Up @@ -1534,6 +1534,7 @@
"ExpenseForm.StepPayeeInvoice": "פרטים על הספק",
"ExpenseForm.Submit": "עדכון הוצאה",
"ExpenseForm.SubmitRequest": "סיום ושליחת הבקשה",
"ExpenseForm.SubmitTo": "Submit expense to {account}",
"ExpenseForm.Type.Request": "בקשת מענק",
"ExpenseFormPayeeStep.PrivateInfo": "This information is private",
"ExpenseFormPayeeStep.PrivateInfoDetails": "The payout method details are private and can only be viewed by the Payee and the Host admins.",
Expand Down
1 change: 1 addition & 0 deletions lang/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -1534,6 +1534,7 @@
"ExpenseForm.StepPayeeInvoice": "Payee information",
"ExpenseForm.Submit": "Invia spese",
"ExpenseForm.SubmitRequest": "Invia richiesta",
"ExpenseForm.SubmitTo": "Submit expense to {account}",
"ExpenseForm.Type.Request": "Request Grant",
"ExpenseFormPayeeStep.PrivateInfo": "This information is private",
"ExpenseFormPayeeStep.PrivateInfoDetails": "The payout method details are private and can only be viewed by the Payee and the Host admins.",
Expand Down
1 change: 1 addition & 0 deletions lang/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -1534,6 +1534,7 @@
"ExpenseForm.StepPayeeInvoice": "支払先情報",
"ExpenseForm.Submit": "経費を申請",
"ExpenseForm.SubmitRequest": "Submit request",
"ExpenseForm.SubmitTo": "Submit expense to {account}",
"ExpenseForm.Type.Request": "Request Grant",
"ExpenseFormPayeeStep.PrivateInfo": "This information is private",
"ExpenseFormPayeeStep.PrivateInfoDetails": "The payout method details are private and can only be viewed by the Payee and the Host admins.",
Expand Down
1 change: 1 addition & 0 deletions lang/ko.json
Original file line number Diff line number Diff line change
Expand Up @@ -1534,6 +1534,7 @@
"ExpenseForm.StepPayeeInvoice": "수취인 정보",
"ExpenseForm.Submit": "경비 제출",
"ExpenseForm.SubmitRequest": "요청 제출",
"ExpenseForm.SubmitTo": "Submit expense to {account}",
"ExpenseForm.Type.Request": "Request Grant",
"ExpenseFormPayeeStep.PrivateInfo": "This information is private",
"ExpenseFormPayeeStep.PrivateInfoDetails": "The payout method details are private and can only be viewed by the Payee and the Host admins.",
Expand Down
1 change: 1 addition & 0 deletions lang/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -1534,6 +1534,7 @@
"ExpenseForm.StepPayeeInvoice": "Payee information",
"ExpenseForm.Submit": "Submit expense",
"ExpenseForm.SubmitRequest": "Aanvraag verzenden",
"ExpenseForm.SubmitTo": "Submit expense to {account}",
"ExpenseForm.Type.Request": "Request Grant",
"ExpenseFormPayeeStep.PrivateInfo": "This information is private",
"ExpenseFormPayeeStep.PrivateInfoDetails": "The payout method details are private and can only be viewed by the Payee and the Host admins.",
Expand Down
1 change: 1 addition & 0 deletions lang/pl.json
Original file line number Diff line number Diff line change
Expand Up @@ -1534,6 +1534,7 @@
"ExpenseForm.StepPayeeInvoice": "Informacje o odbiorcy",
"ExpenseForm.Submit": "Prześlij wydatki",
"ExpenseForm.SubmitRequest": "Wyślij wniosek",
"ExpenseForm.SubmitTo": "Submit expense to {account}",
"ExpenseForm.Type.Request": "Wniosek o dotację",
"ExpenseFormPayeeStep.PrivateInfo": "This information is private",
"ExpenseFormPayeeStep.PrivateInfoDetails": "The payout method details are private and can only be viewed by the Payee and the Host admins.",
Expand Down
1 change: 1 addition & 0 deletions lang/pt-BR.json
Original file line number Diff line number Diff line change
Expand Up @@ -1534,6 +1534,7 @@
"ExpenseForm.StepPayeeInvoice": "Informações do beneficiário",
"ExpenseForm.Submit": "Enviar despesa",
"ExpenseForm.SubmitRequest": "Enviar solicitação",
"ExpenseForm.SubmitTo": "Submit expense to {account}",
"ExpenseForm.Type.Request": "Solicitação de concessão",
"ExpenseFormPayeeStep.PrivateInfo": "Essa informação é privada",
"ExpenseFormPayeeStep.PrivateInfoDetails": "Os detalhes do método de pagamento são privados e só podem ser vistos pelo beneficiário e os administradores.",
Expand Down
1 change: 1 addition & 0 deletions lang/pt.json
Original file line number Diff line number Diff line change
Expand Up @@ -1534,6 +1534,7 @@
"ExpenseForm.StepPayeeInvoice": "Payee information",
"ExpenseForm.Submit": "Enviar despesa",
"ExpenseForm.SubmitRequest": "Submit request",
"ExpenseForm.SubmitTo": "Submit expense to {account}",
"ExpenseForm.Type.Request": "Request Grant",
"ExpenseFormPayeeStep.PrivateInfo": "This information is private",
"ExpenseFormPayeeStep.PrivateInfoDetails": "The payout method details are private and can only be viewed by the Payee and the Host admins.",
Expand Down
1 change: 1 addition & 0 deletions lang/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -1534,6 +1534,7 @@
"ExpenseForm.StepPayeeInvoice": "Информация о получателе",
"ExpenseForm.Submit": "Отправить расходы",
"ExpenseForm.SubmitRequest": "Отправить расходы",
"ExpenseForm.SubmitTo": "Submit expense to {account}",
"ExpenseForm.Type.Request": "Запросить грант",
"ExpenseFormPayeeStep.PrivateInfo": "This information is private",
"ExpenseFormPayeeStep.PrivateInfoDetails": "The payout method details are private and can only be viewed by the Payee and the Host admins.",
Expand Down
1 change: 1 addition & 0 deletions lang/sk-SK.json
Original file line number Diff line number Diff line change
Expand Up @@ -1534,6 +1534,7 @@
"ExpenseForm.StepPayeeInvoice": "Informácie o príjemcovi",
"ExpenseForm.Submit": "Predložiť výdavok",
"ExpenseForm.SubmitRequest": "Predložiť požiadavku",
"ExpenseForm.SubmitTo": "Submit expense to {account}",
"ExpenseForm.Type.Request": "Žiadosť o grant",
"ExpenseFormPayeeStep.PrivateInfo": "This information is private",
"ExpenseFormPayeeStep.PrivateInfoDetails": "The payout method details are private and can only be viewed by the Payee and the Host admins.",
Expand Down
1 change: 1 addition & 0 deletions lang/sv-SE.json
Original file line number Diff line number Diff line change
Expand Up @@ -1534,6 +1534,7 @@
"ExpenseForm.StepPayeeInvoice": "Betalningsmottagarens information",
"ExpenseForm.Submit": "Skicka in utgift",
"ExpenseForm.SubmitRequest": "Skicka begäran",
"ExpenseForm.SubmitTo": "Submit expense to {account}",
"ExpenseForm.Type.Request": "Begär bidrag",
"ExpenseFormPayeeStep.PrivateInfo": "This information is private",
"ExpenseFormPayeeStep.PrivateInfoDetails": "The payout method details are private and can only be viewed by the Payee and the Host admins.",
Expand Down
1 change: 1 addition & 0 deletions lang/uk.json
Original file line number Diff line number Diff line change
Expand Up @@ -1534,6 +1534,7 @@
"ExpenseForm.StepPayeeInvoice": "Дані одержувача",
"ExpenseForm.Submit": "Надіслати витрату",
"ExpenseForm.SubmitRequest": "Надіслати запит",
"ExpenseForm.SubmitTo": "Submit expense to {account}",
"ExpenseForm.Type.Request": "Request Grant",
"ExpenseFormPayeeStep.PrivateInfo": "This information is private",
"ExpenseFormPayeeStep.PrivateInfoDetails": "The payout method details are private and can only be viewed by the Payee and the Host admins.",
Expand Down
1 change: 1 addition & 0 deletions lang/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -1534,6 +1534,7 @@
"ExpenseForm.StepPayeeInvoice": "收款人信息",
"ExpenseForm.Submit": "提交支出",
"ExpenseForm.SubmitRequest": "提交请求",
"ExpenseForm.SubmitTo": "Submit expense to {account}",
"ExpenseForm.Type.Request": "请求授权",
"ExpenseFormPayeeStep.PrivateInfo": "This information is private",
"ExpenseFormPayeeStep.PrivateInfoDetails": "The payout method details are private and can only be viewed by the Payee and the Host admins.",
Expand Down

0 comments on commit 3801674

Please sign in to comment.