Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions src/taxes/components/TaxCountryDialog/TaxCountryDialog.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// @ts-strict-ignore
import { DashboardModal } from "@dashboard/components/Modal";
import { CountryFragment } from "@dashboard/graphql";
import { useLocalSearch } from "@dashboard/hooks/useLocalSearch";
Expand Down Expand Up @@ -70,7 +69,7 @@ const TaxCountryDialog = ({ open, countries, onConfirm, onClose }: TaxCountryDia
__marginLeft={-15}
__paddingLeft={15}
>
{filteredCountries.map(country => (
{filteredCountries?.map(country => (
<Fragment key={country.code}>
<FormControlLabel
data-test-id="country-row"
Expand All @@ -89,7 +88,9 @@ const TaxCountryDialog = ({ open, countries, onConfirm, onClose }: TaxCountryDia
data-test-id="add-button"
variant="primary"
onClick={() => {
onConfirm(selectedCountry);
if (selectedCountry) {
onConfirm(selectedCountry);
}
}}
disabled={!selectedCountry}
>
Expand Down
13 changes: 10 additions & 3 deletions src/taxes/pages/TaxChannelsPage/TaxChannelsPage.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// @ts-strict-ignore
import { TopNav } from "@dashboard/components/AppLayout/TopNav";
import CardTitle from "@dashboard/components/CardTitle";
import { ConfirmButtonTransitionState } from "@dashboard/components/ConfirmButton";
Expand Down Expand Up @@ -125,7 +124,10 @@ const TaxChannelsPage = (props: TaxChannelsPageProps) => {
<Form initial={initialForm} onSubmit={handleSubmit} mergeData={false}>
{({ data, change, submit, set, triggerChange }) => {
const countryExceptions = data.updateCountriesConfiguration;
const handleExceptionChange = (event, index) => {
const handleExceptionChange = (
event: React.ChangeEvent<HTMLInputElement>,
index: number,
) => {
const { name, value } = event.target;
const currentExceptions = [...data.updateCountriesConfiguration];
const exceptionToChange = {
Expand Down Expand Up @@ -254,7 +256,12 @@ const TaxChannelsPage = (props: TaxChannelsPageProps) => {
});
triggerChange();
}}
onChange={event => handleExceptionChange(event, countryIndex)}
onChange={event =>
handleExceptionChange(
event as React.ChangeEvent<HTMLInputElement>,
countryIndex,
)
}
/>
)) ?? <Skeleton />}
</List>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// @ts-strict-ignore
import ControlledCheckbox from "@dashboard/components/ControlledCheckbox";
import { Select } from "@dashboard/components/Select";
import { TaxConfigurationUpdateInput } from "@dashboard/graphql";
Expand Down Expand Up @@ -30,6 +29,10 @@ const TaxCountryExceptionListItem = ({
}: TaxCountryExceptionListItemProps) => {
const classes = useStyles();

if (!country) {
return null;
}

return (
<>
<ListItem hover={false} className={classes.noDivider} data-test-id="exception-country">
Expand Down
7 changes: 5 additions & 2 deletions src/taxes/pages/TaxChannelsPage/helpers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@ export const getTaxAppId = (taxCalculationStrategy: string) =>
isStrategyFlatRates(taxCalculationStrategy) ? null : taxCalculationStrategy;

export const getSelectedTaxStrategy = (
currentTaxConfiguration: TaxConfigurationFragment | TaxConfigurationPerCountryFragment,
currentTaxConfiguration:
| TaxConfigurationFragment
| TaxConfigurationPerCountryFragment
| undefined,
) =>
isStrategyFlatRates(currentTaxConfiguration?.taxCalculationStrategy)
isStrategyFlatRates(currentTaxConfiguration?.taxCalculationStrategy ?? null)
? TaxCalculationStrategy.FLAT_RATES
: (currentTaxConfiguration?.taxAppId ?? "legacy-flow");
3 changes: 1 addition & 2 deletions src/taxes/pages/TaxClassesPage/form.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// @ts-strict-ignore
import { useExitFormDialog } from "@dashboard/components/Form/useExitFormDialog";
import { TaxClassFragment } from "@dashboard/graphql";
import useForm, { FormChange, SubmitPromise } from "@dashboard/hooks/useForm";
Expand Down Expand Up @@ -34,7 +33,7 @@ interface TaxClassesFormProps {
}

function useTaxClassesForm(
taxClass: TaxClassFragment,
taxClass: TaxClassFragment | undefined,
onTaxClassCreate: (data: TaxClassesPageFormData) => SubmitPromise<TaxClassError[]>,
onTaxClassUpdate: (data: TaxClassesPageFormData) => SubmitPromise<TaxClassError[]>,
disabled: boolean,
Expand Down
56 changes: 34 additions & 22 deletions src/taxes/pages/TaxCountriesPage/TaxCountriesPage.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// @ts-strict-ignore
import { TopNav } from "@dashboard/components/AppLayout/TopNav";
import CardTitle from "@dashboard/components/CardTitle";
import { ConfirmButtonTransitionState } from "@dashboard/components/ConfirmButton";
Expand Down Expand Up @@ -68,11 +67,15 @@ const TaxCountriesPage = (props: TaxCountriesPageProps) => {
[selectedCountryId, countryTaxesData],
);

if (!currentCountry) {
return null;
}

return (
<TaxCountriesForm country={currentCountry} onSubmit={onSubmit} disabled={disabled}>
{({ data, handlers, submit }) => {
const filteredRates = data?.filter(
rate => rate.label.search(new RegExp(parseQuery(query), "i")) >= 0,
(rate: { label: string }) => rate.label.search(new RegExp(parseQuery(query), "i")) >= 0,
);

return (
Expand Down Expand Up @@ -102,7 +105,9 @@ const TaxCountriesPage = (props: TaxCountriesPageProps) => {
<TaxCountriesMenu
configurations={countryTaxesData}
selectedCountryId={selectedCountryId}
onCountryDelete={onDeleteConfiguration}
onCountryDelete={(countryId: string) => {
onDeleteConfiguration(countryId as CountryCode);
}}
onCountryAdd={() => openDialog("add-country")}
/>
<Card>
Expand Down Expand Up @@ -156,25 +161,32 @@ const TaxCountriesPage = (props: TaxCountriesPageProps) => {
</ListItem>
</ListHeader>
<Divider />
{filteredRates?.map((rate, rateIndex) => (
<Fragment key={rate.id}>
<ListItem
hover={false}
className={classes.noDivider}
data-test-id={rate.label}
>
<ListItemCell>{rate.label}</ListItemCell>
<ListItemCell>
<TaxInput
placeholder={data[0]?.rate}
value={rate?.value}
change={e => handlers.handleRateChange(rate.id, e.target.value)}
/>
</ListItemCell>
</ListItem>
{!isLastElement(filteredRates, rateIndex) && <Divider />}
</Fragment>
)) ?? <Skeleton />}
{filteredRates?.map(
(
rate: { id: string; label: string; value?: string },
rateIndex: number,
) => (
<Fragment key={rate.id}>
<ListItem
hover={false}
className={classes.noDivider}
data-test-id={rate.label}
>
<ListItemCell>{rate.label}</ListItemCell>
<ListItemCell>
<TaxInput
placeholder={data[0]?.rate}
value={rate?.value}
change={e =>
handlers.handleRateChange(rate.id, e.target.value)
}
/>
</ListItemCell>
</ListItem>
{!isLastElement(filteredRates, rateIndex) && <Divider />}
</Fragment>
),
) ?? <Skeleton />}
</List>
</>
)}
Expand Down
9 changes: 4 additions & 5 deletions src/taxes/pages/TaxCountriesPage/form.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// @ts-strict-ignore
import { useExitFormDialog } from "@dashboard/components/Form/useExitFormDialog";
import { TaxClassRateInput, TaxCountryConfigurationFragment } from "@dashboard/graphql";
import useForm, { SubmitPromise } from "@dashboard/hooks/useForm";
Expand All @@ -23,21 +22,21 @@ interface TaxCountriesFormProps {

function useTaxCountriesForm(
country: TaxCountryConfigurationFragment,
onSubmit,
disabled,
onSubmit: (data: TaxClassRateInput[]) => SubmitPromise,
disabled: boolean,
): UseTaxCountriesFormResult {
// Initial
const intl = useIntl();
const initialFormsetData = country?.taxClassCountryRates.map(item => ({
id: item.taxClass?.id ?? null,
label: item.taxClass?.name ?? intl.formatMessage(taxesMessages.countryDefaultRate),
value: item.rate?.toString() ?? "",
data: null,
data: null as any,
Copy link

Copilot AI Nov 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The type assertion data: null as any bypasses type safety. Consider defining a proper type for this field or using the actual expected type instead of any.

Suggested change
data: null as any,
data: null,

Copilot uses AI. Check for mistakes.
}));
const { formId, triggerChange } = useForm({}, undefined, {
confirmLeave: true,
});
const formset = useFormset(initialFormsetData);
const formset = useFormset(initialFormsetData as any);
Copy link

Copilot AI Nov 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The type assertion as any bypasses type safety for the formset data. Consider properly typing the formset initial data to match the expected type instead of using any.

Copilot uses AI. Check for mistakes.
// Handlers
const handleRateChange = (id: string, value: string) => {
triggerChange();
Expand Down
26 changes: 13 additions & 13 deletions src/taxes/utils/data.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// @ts-strict-ignore
import {
CountryCode,
CountryRateInput,
Expand All @@ -12,20 +11,21 @@ import { mapMetadataItemToInput } from "@dashboard/utils/maps";
import { TaxClassesPageFormData } from "../types";

export const getTaxClassInitialFormData = (taxClass?: TaxClassFragment): TaxClassesPageFormData => {
const initialCountries = taxClass?.countries
.map(item => ({
id: item.country.code,
label: item.country.country,
value: item.rate?.toString() ?? "",
data: null,
}))
.sort((a, b) => a.label.localeCompare(b.label));
const initialCountries =
taxClass?.countries
.map(item => ({
id: item.country.code,
label: item.country.country,
value: item.rate?.toString() ?? "",
data: null as any,
Copy link

Copilot AI Nov 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The type assertion data: null as any bypasses type safety. If data needs to be any, consider defining a proper type or interface for this field. If it's genuinely unused, consider using undefined or the actual expected type.

Suggested change
data: null as any,
data: undefined,

Copilot uses AI. Check for mistakes.
}))
.sort((a, b) => a.label.localeCompare(b.label)) ?? [];

return {
id: taxClass?.id,
id: taxClass?.id ?? "",
name: taxClass?.name ?? "",
metadata: taxClass?.metadata?.map(mapMetadataItemToInput),
privateMetadata: taxClass?.privateMetadata?.map(mapMetadataItemToInput),
metadata: taxClass?.metadata?.map(mapMetadataItemToInput) ?? [],
privateMetadata: taxClass?.privateMetadata?.map(mapMetadataItemToInput) ?? [],
updateTaxClassRates: initialCountries,
};
};
Expand All @@ -36,7 +36,7 @@ const createCountryRateInput = ({ id, value }: FormsetAtomicData): CountryRateIn
});

export const createTaxClassCreateInput = (data: TaxClassesPageFormData): TaxClassCreateInput => ({
name: data.name,
name: data.name || "",
createCountryRates: data.updateTaxClassRates.flatMap(item => {
if (!item.value) {
return [];
Expand Down
13 changes: 8 additions & 5 deletions src/taxes/utils/useTaxClassFetchMore.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// @ts-strict-ignore
import { TaxClassBaseFragment, useTaxClassAssignQuery } from "@dashboard/graphql";
import { FetchMoreProps } from "@dashboard/types";
import { mapEdgesToItems } from "@dashboard/utils/maps";
Expand All @@ -21,14 +20,18 @@ export function useTaxClassFetchMore(): UseTaxClassFetchMoreHookResult {
first: 20,
},
});
const taxClasses = mapEdgesToItems(data?.taxClasses);
const fetchMoreTaxClasses = {
hasMore: data?.taxClasses?.pageInfo?.hasNextPage,
const taxClasses = mapEdgesToItems(data?.taxClasses) ?? [];
const fetchMoreTaxClasses: FetchMoreProps = {
hasMore: data?.taxClasses?.pageInfo?.hasNextPage ?? false,
loading,
onFetchMore: () => {
loadMore(
(prev, next) => {
if (prev.taxClasses.pageInfo.endCursor === next.taxClasses.pageInfo.endCursor) {
if (
!prev.taxClasses ||
!next.taxClasses ||
prev.taxClasses.pageInfo.endCursor === next.taxClasses.pageInfo.endCursor
) {
return prev;
}

Expand Down
15 changes: 7 additions & 8 deletions src/taxes/utils/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// @ts-strict-ignore
import {
CountryFragment,
TaxClassFragment,
Expand Down Expand Up @@ -29,7 +28,7 @@ export const mapUndefinedTaxRatesToCountries = (
...config.taxClassCountryRates,
...taxClasses.map(taxClass => ({
taxClass,
rate: undefined,
rate: null,
Copy link

Copilot AI Nov 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The rate field is set to null but according to the GraphQL schema, rate should be number (non-nullable). This creates a runtime type mismatch between the local state and the GraphQL type. Consider using a default value like 0 or undefined placeholder that's handled appropriately, or creating a separate type for partially-initialized tax rates.

Copilot uses AI. Check for mistakes.
__typename: "TaxClassCountryRate" as const,
})),
],
Expand All @@ -39,16 +38,16 @@ export const mapUndefinedTaxRatesToCountries = (
const parsedCountryRates = taxClassCountryRates.filter(rate => rate.taxClass !== null);

parsedCountryRates.unshift(
defaultRate ?? {
rate: undefined,
(defaultRate ?? {
rate: null,
Copy link

Copilot AI Nov 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The rate field is set to null but according to the GraphQL schema, rate should be number (non-nullable). This creates a type mismatch. Consider using a default value like 0 instead.

Copilot uses AI. Check for mistakes.
taxClass: null,
__typename: "TaxClassCountryRate" as const,
},
}) as any,
Copy link

Copilot AI Nov 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The type assertion as any bypasses type safety. According to the TaxClassCountryRate type, both taxClass: null and the object structure are already valid without needing as any. Consider removing the unnecessary type cast.

Copilot uses AI. Check for mistakes.
);

return {
...config,
taxClassCountryRates: parsedCountryRates,
taxClassCountryRates: parsedCountryRates as typeof config.taxClassCountryRates,
Copy link

Copilot AI Nov 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The type assertion as typeof config.taxClassCountryRates is overly complex. Consider restructuring the code to avoid this type cast, or ensure that parsedCountryRates naturally matches the expected type without forcing it.

Copilot uses AI. Check for mistakes.
};
}
})
Expand All @@ -65,12 +64,12 @@ export const mapUndefinedCountriesToTaxClasses = (
...taxClass.countries,
...taxConfigurations.map(({ country }) => ({
__typename: "TaxClassCountryRate" as const,
rate: undefined,
rate: null,
Copy link

Copilot AI Nov 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The rate field is set to null but according to the GraphQL schema, rate should be number (non-nullable). This creates a type mismatch. Consider using a default value like 0 instead.

Copilot uses AI. Check for mistakes.
country,
})),
],
"country.code",
),
) as typeof taxClass.countries,
Copy link

Copilot AI Nov 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The type assertion as typeof taxClass.countries is overly complex. Consider restructuring the code to avoid this type cast, or ensure the uniqueBy operation naturally maintains the correct type.

Copilot uses AI. Check for mistakes.
}));

export const isLastElement = (arr: any[], index: number): boolean => index === arr.length - 1;
Expand Down
13 changes: 6 additions & 7 deletions src/taxes/views/TaxChannelsList.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// @ts-strict-ignore
import {
useTaxConfigurationsListQuery,
useTaxConfigurationUpdateMutation,
Expand Down Expand Up @@ -38,7 +37,7 @@ const TaxChannelsList = ({ id, params }: TaxChannelsListProps) => {
onCompleted: data => {
const errors = data?.taxConfigurationUpdate?.errors;

if (errors.length === 0) {
if (errors && errors.length === 0) {
notify({
status: "success",
text: intl.formatMessage(commonMessages.savedChanges),
Expand All @@ -50,7 +49,7 @@ const TaxChannelsList = ({ id, params }: TaxChannelsListProps) => {
const [openDialog, closeDialog] = createDialogActionHandlers<TaxesUrlDialog, TaxesUrlQueryParams>(
navigate,
params => taxConfigurationListUrl(id, params),
params,
params ?? {},
);
const { data } = useTaxConfigurationsListQuery({ variables: { first: 100 } });
const taxConfigurations = mapEdgesToItems(data?.taxConfigurations);
Expand All @@ -69,16 +68,16 @@ const TaxChannelsList = ({ id, params }: TaxChannelsListProps) => {
return (
<TaxChannelsPage
taxConfigurations={taxConfigurations}
selectedConfigurationId={id!}
handleTabChange={handleTabChange}
selectedConfigurationId={id ?? ""}
handleTabChange={(tab: string) => handleTabChange(tab as TaxTab)}
allCountries={shop?.countries}
isDialogOpen={params?.action === "add-country"}
openDialog={openDialog}
openDialog={(action?: string) => openDialog(action as TaxesUrlDialog)}
closeDialog={closeDialog}
onSubmit={input =>
taxConfigurationUpdateMutation({
variables: {
id,
id: id ?? "",
input,
},
})
Expand Down
Loading
Loading