Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace any with Generic Types in POST and PUT Requests #2358

Draft
wants to merge 6 commits into
base: develop
Choose a base branch
from
Draft
Changes from 1 commit
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
11 changes: 9 additions & 2 deletions pages/sites/[slug]/[locale]/claim/[type]/[code].tsx
Original file line number Diff line number Diff line change
@@ -35,6 +35,10 @@ interface Props {
pageProps: PageProps;
}

export type RedeemCodeSubmitData = {
code: string;
};

function ClaimDonation({ pageProps }: Props): ReactElement {
const t = useTranslations('Redeem');
const router = useRouter();
@@ -79,12 +83,15 @@ function ClaimDonation({ pageProps }: Props): ReactElement {
};

async function redeemingCode(code: string): Promise<void> {
const submitData = {
const submitData: RedeemCodeSubmitData = {
code: code,
};
if (contextLoaded && user) {
try {
const res = await postAuthenticatedRequest<RedeemedCodeData>({
const res = await postAuthenticatedRequest<
RedeemedCodeData,
RedeemCodeSubmitData
>({
tenant: pageProps.tenantConfig.id,
url: `/app/redeem`,
data: submitData,
8 changes: 6 additions & 2 deletions pages/sites/[slug]/[locale]/profile/redeem/[code].tsx
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@ import type { AbstractIntlMessages } from 'next-intl';
import type { APIError, SerializedError } from '@planet-sdk/common';
import type { Tenant } from '@planet-sdk/common/build/types/tenant';
import type { RedeemedCodeData } from '../../../../../../src/features/common/types/redeem';
import type { RedeemCodeSubmitData } from '../../claim/[type]/[code]';

import { useRouter } from 'next/router';
import { useState, useEffect, useContext } from 'react';
@@ -73,13 +74,16 @@ const RedeemCode = ({ pageProps: { tenantConfig } }: Props) => {

async function redeemingCode(data: string): Promise<void> {
setIsLoading(true);
const submitData = {
const submitData: RedeemCodeSubmitData = {
code: data,
};

if (contextLoaded && user) {
try {
const res = await postAuthenticatedRequest<RedeemedCodeData>({
const res = await postAuthenticatedRequest<
RedeemedCodeData,
RedeemCodeSubmitData
>({
tenant: tenantConfig?.id,
url: `/app/redeem`,
data: submitData,
5 changes: 4 additions & 1 deletion src/features/user/BulkCodes/forms/IssueCodesForm.tsx
Original file line number Diff line number Diff line change
@@ -152,7 +152,10 @@ const IssueCodesForm = (): ReactElement | null => {
const cleanedData = cleanObject(donationData);

try {
const res = await postAuthenticatedRequest<Donation>({
const res = await postAuthenticatedRequest<
Donation,
PrepaidDonationRequest
>({
tenant: tenantConfig?.id,
url: `/app/donations`,
data: cleanedData,
19 changes: 17 additions & 2 deletions src/features/user/ManagePayouts/screens/AddBankAccount.tsx
Original file line number Diff line number Diff line change
@@ -17,6 +17,21 @@ import { PayoutCurrency } from '../../../../utils/constants/payoutConstants';
import { handleError } from '@planet-sdk/common';
import { useTenant } from '../../../common/Layout/TenantContext';

interface AccountData {
currency: string;
payoutMinAmount: string | undefined;
bankName: string;
bankCountry: string;
bankAddress: string;
holderName: string;
holderAddress: string;
accountNumber: string;
routingNumber: string;
bic: string;
branchCode: string;
remarks: string;
}

const AddBankAccount = (): ReactElement | null => {
const t = useTranslations('ManagePayouts');
const { payoutMinAmounts, setAccounts, accounts } = usePayouts();
@@ -32,14 +47,14 @@ const AddBankAccount = (): ReactElement | null => {

const handleSaveAccount = async (data: FormData) => {
setIsProcessing(true);
const accountData = {
const accountData: AccountData = {
...data,
currency: data.currency === PayoutCurrency.DEFAULT ? '' : data.currency,
payoutMinAmount:
data.currency === PayoutCurrency.DEFAULT ? '' : data.payoutMinAmount,
};
try {
const res = await postAuthenticatedRequest<BankAccount>({
const res = await postAuthenticatedRequest<BankAccount, AccountData>({
tenant: tenantConfig?.id,
url: '/app/accounts',
data: accountData,
35 changes: 33 additions & 2 deletions src/features/user/ManageProjects/components/BasicDetails.tsx
Original file line number Diff line number Diff line change
@@ -66,6 +66,36 @@

type ConservationFormData = FormData;

interface SubmitDataBase {
name: string;
slug: string;
website: string;
description: string;
acceptDonations: boolean;
unitCost: number | undefined;
currency: 'EUR'; // Fixed currency
metadata: {
ecosystem: string;
visitorAssistance: boolean;
};
geometry: {
type: 'Point';
coordinates: [number, number];
};
}

interface SubmitDataTrees extends SubmitDataBase {
unitType: 'tree' | 'm2';
classification: string;
countTarget: number;
}

interface SubmitDataConservation extends SubmitDataBase {
purpose: 'conservation';
}

type SubmitData = SubmitDataTrees | SubmitDataConservation;

export default function BasicDetails({
handleNext,
token,
@@ -242,71 +272,71 @@
}
}, [router]);

useEffect(() => {
if (projectDetails) {
const basicDetails =
purpose === 'trees'
? {
name: projectDetails.name,
slug: projectDetails.slug,
website: projectDetails.website || '',
description: projectDetails.description,
acceptDonations: projectDetails.acceptDonations,
unitType: projectDetails.unitType,
unitCost: getFormattedNumber(
locale,
projectDetails.unitCost || 0
),
latitude: projectDetails.geoLatitude.toString(),
longitude: projectDetails.geoLongitude.toString(),
metadata: {
visitorAssistance:
projectDetails.metadata.visitorAssistance || false,
ecosystem: projectDetails.metadata.ecosystem || '',
},
classification: projectDetails.classification || '',
countTarget: projectDetails.countTarget || '',
}
: {
name: projectDetails.name,
slug: projectDetails.slug,
website: projectDetails.website || '',
description: projectDetails.description,
acceptDonations: projectDetails.acceptDonations,
unitCost: getFormattedNumber(
locale,
projectDetails.unitCost || 0
),
latitude: projectDetails.geoLatitude.toString(),
longitude: projectDetails.geoLongitude.toString(),
metadata: {
visitorAssistance:
projectDetails.metadata.visitorAssistance || false,
ecosystem: projectDetails.metadata.ecosystem || '',
},
};
if (projectDetails.geoLongitude && projectDetails.geoLatitude) {
setProjectCoords([
projectDetails.geoLongitude,
projectDetails.geoLatitude,
]);
setViewPort({
...viewport,
latitude: projectDetails.geoLatitude,
longitude: projectDetails.geoLongitude,
zoom: 7,
});
}
reset(basicDetails);
if (projectDetails.acceptDonations) {
setAcceptDonations(projectDetails.acceptDonations);
}
}
}, [projectDetails]);

Check notice on line 336 in src/features/user/ManageProjects/components/BasicDetails.tsx

codefactor.io / CodeFactor

src/features/user/ManageProjects/components/BasicDetails.tsx#L275-L336

Complex Method
const onSubmit = async (data: TreeFormData | ConservationFormData) => {
setIsUploadingData(true);
const submitData =
const submitData: SubmitData =
purpose === 'trees'
? {
name: data.name,
@@ -379,7 +409,8 @@
} else {
try {
const res = await postAuthenticatedRequest<
ProfileProjectTrees | ProfileProjectConservation
ProfileProjectTrees | ProfileProjectConservation,
SubmitData
>({
tenant: tenantConfig?.id,
url: `/app/projects`,
Original file line number Diff line number Diff line change
@@ -48,6 +48,12 @@ const dialogSx: SxProps = {
},
};

type SubmitData = {
issueDate: string;
certifierName: string;
pdfFile: string;
};

function ProjectCertificates({
projectGUID,
token,
@@ -78,14 +84,14 @@ function ProjectCertificates({
const onSubmit = async (pdf: string) => {
const { issueDate, certifierName } = getValues();
setIsUploadingData(true);
const submitData = {
const submitData: SubmitData = {
issueDate: issueDate.getFullYear(),
certifierName: certifierName,
pdfFile: pdf,
};
Comment on lines +87 to 91
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Codebase verification

The review comment is valid - there's data loss when converting full date to year.

The code shows an inconsistency:

  • The UI collects full date information through MuiDatePicker
  • The display component shows the full date string: <p>{report.issueDate} </p>
  • However, during submission, the full date is reduced to just the year: issueDate: issueDate.getFullYear()

This unnecessary data transformation results in loss of month and day information that the UI is designed to collect and display.

🔗 Analysis chain

Consider preserving full date information.

The issueDate is being converted to just the year, which loses month and day information. Consider storing the full date if this information might be valuable.

Run this script to check if other parts of the system rely on or display the full date:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for usage of certificate issue dates in the codebase
rg -A 3 "issueDate" --type ts --type tsx

Length of output: 68


Script:

#!/bin/bash
# Search for issueDate in TypeScript files
echo "=== Searching in .ts and .tsx files ==="
rg "issueDate" . -g "*.ts" -g "*.tsx" -B 2 -A 2

echo -e "\n=== Looking for certificate-related interfaces/types ==="
ast-grep --pattern 'interface $_ {
  $$$
  issueDate
  $$$
}'

echo -e "\n=== Looking for date formatting/display patterns ==="
rg "new Date|Date\." . -g "*.ts" -g "*.tsx" -B 1 -A 1

Length of output: 31912


try {
const res = await postAuthenticatedRequest<Certificate>({
const res = await postAuthenticatedRequest<Certificate, SubmitData>({
tenant: tenantConfig?.id,
url: `/app/projects/${projectGUID}/certificates`,
data: submitData,
10 changes: 8 additions & 2 deletions src/features/user/ManageProjects/components/ProjectMedia.tsx
Original file line number Diff line number Diff line change
@@ -33,6 +33,12 @@ import { useUserProps } from '../../../common/Layout/UserPropsContext';
import { ProjectCreationTabs } from '..';
import { useTenant } from '../../../common/Layout/TenantContext';

type SubmitData = {
imageFile: string;
description: string | null;
isDefault: boolean;
};

export default function ProjectMedia({
handleBack,
token,
@@ -84,14 +90,14 @@ export default function ProjectMedia({
const uploadPhotos = async (image: string) => {
setIsUploadingData(true);

const submitData = {
const submitData: SubmitData = {
imageFile: image,
description: null,
isDefault: false,
};

try {
const res = await postAuthenticatedRequest<UploadImage>({
const res = await postAuthenticatedRequest<UploadImage, SubmitData>({
tenant: tenantConfig?.id,
url: `/app/projects/${projectGUID}/images`,
data: submitData,
16 changes: 13 additions & 3 deletions src/features/user/ManageProjects/components/ProjectSites.tsx
Original file line number Diff line number Diff line change
@@ -8,7 +8,11 @@ import type {
Site,
SitesScopeProjects,
} from '../../../common/types/project';
import type { FeatureCollection as GeoJson } from 'geojson';
import type {
FeatureCollection as GeoJson,
GeoJsonProperties,
Geometry,
} from 'geojson';

import React from 'react';
import styles from './../StepForm.module.scss';
@@ -258,6 +262,12 @@ interface ProjectSitesFormData {
status: string;
}

type SubmitData = {
name: string;
geometry: GeoJson<Geometry, GeoJsonProperties>;
status: string;
};

export default function ProjectSites({
handleBack,
token,
@@ -369,14 +379,14 @@ export default function ProjectSites({
if (!data.name) return;

setIsUploadingData(true);
const submitData = {
const submitData: SubmitData = {
name: siteDetails.name,
geometry: geoJson,
status: data.status,
};

try {
const res = await postAuthenticatedRequest<Site>({
const res = await postAuthenticatedRequest<Site, SubmitData>({
tenant: tenantConfig?.id,
url: `/app/projects/${projectGUID}/sites`,
data: submitData,
10 changes: 7 additions & 3 deletions src/features/user/ManageProjects/components/ProjectSpending.tsx
Original file line number Diff line number Diff line change
@@ -56,7 +56,11 @@ type FormData = {
year: Date;
amount: number;
};

type SubmitData = {
year: number;
amount: number;
pdfFile: string | ArrayBuffer | null | undefined;
};
export default function ProjectSpending({
handleBack,
token,
@@ -88,14 +92,14 @@ export default function ProjectSpending({
const updatedAmount = getValues('amount');
const year = getValues('year');

const submitData = {
const submitData: SubmitData = {
year: year.getFullYear(),
amount: updatedAmount,
pdfFile: pdf,
};

try {
const res = await postAuthenticatedRequest<ProjectExpense>({
const res = await postAuthenticatedRequest<ProjectExpense, SubmitData>({
tenant: tenantConfig?.id,
url: `/app/projects/${projectGUID}/expenses`,
data: submitData,
23 changes: 21 additions & 2 deletions src/features/user/PlanetCash/components/CreateAccountForm.tsx
Original file line number Diff line number Diff line change
@@ -25,6 +25,25 @@
allowedCountries: CountryType[];
}

type SubmitData = {
country: ExtendedCountryCode | string;
activate: boolean;
};

type PlanetCash = {
id: string;
isActive: boolean;
ownerName: string;
balance: number;
debit: number;
fee: number;
creditLimit: number;
currency: 'EUR' | 'USD';
country: 'DE' | 'ES' | 'US';
topUpThreshold: number;
topUpAmount: number;
};

const CreateAccountForm = ({
allowedCountries,
isPlanetCashActive,
@@ -42,11 +61,11 @@

const onSubmit = async (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
const data = { country: country, activate: !isPlanetCashActive };
const data: Data = { country: country, activate: !isPlanetCashActive };

Check notice on line 64 in src/features/user/PlanetCash/components/CreateAccountForm.tsx

codefactor.io / CodeFactor

src/features/user/PlanetCash/components/CreateAccountForm.tsx#L64

'Data' is not defined. (no-undef)
Copy link
Contributor

@coderabbitai coderabbitai bot Jan 10, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix undefined type 'Data'.

The type 'Data' is not defined. Replace it with the newly defined 'SubmitData' type.

-    const data: Data = { country: country, activate: !isPlanetCashActive };
+    const data: SubmitData = { country: country, activate: !isPlanetCashActive };

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 GitHub Check: CodeFactor

[notice] 64-64: src/features/user/PlanetCash/components/CreateAccountForm.tsx#L64
'Data' is not defined. (no-undef)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

Copy link
Contributor

Choose a reason for hiding this comment

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

@sunilsabatp Thanks for fixing the issue! 🎉


If you found this review helpful, would you consider giving us a shout-out on X?
Thank you for using CodeRabbit!

setIsProcessing(true);

try {
const res = await postAuthenticatedRequest({
const res = await postAuthenticatedRequest<PlanetCash, SubmitData>({
tenant: tenantConfig?.id,
url: '/app/planetCash',
data,
10 changes: 7 additions & 3 deletions src/features/user/Profile/ProfileCard/RedeemModal/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { ReactElement } from 'react';
import type { APIError, SerializedError } from '@planet-sdk/common';
import type { RedeemedCodeData } from '../../../../common/types/redeem';
import type { RedeemCodeSubmitData } from '../../../../../../pages/sites/[slug]/[locale]/claim/[type]/[code]';

import Modal from '@mui/material/Modal';
import Fade from '@mui/material/Fade';
@@ -43,14 +44,17 @@ export default function RedeemModal({
RedeemedCodeData | undefined
>(undefined);
const [isLoading, setIsLoading] = React.useState<boolean>(false);
async function redeemingCode(data: string | undefined): Promise<void> {
async function redeemingCode(data: string): Promise<void> {
setIsLoading(true);
const submitData = {
const submitData: RedeemCodeSubmitData = {
code: data,
};
if (contextLoaded && user) {
try {
const res = await postAuthenticatedRequest<RedeemedCodeData>({
const res = await postAuthenticatedRequest<
RedeemedCodeData,
RedeemCodeSubmitData
>({
tenant: tenantConfig?.id,
url: `/app/redeem`,
data: submitData,
Original file line number Diff line number Diff line change
@@ -23,6 +23,11 @@ interface Props {
token: string | null;
}

type SubmitData = {
imageFile: string;
description: string;
};

export default function UploadImages({
contributionGUID,
token,
@@ -36,13 +41,13 @@ export default function UploadImages({

const uploadPhotos = async (image: string) => {
setIsUploadingData(true);
const submitData = {
const submitData: SubmitData = {
imageFile: image,
description: '',
};

try {
const res = await postAuthenticatedRequest<Image>({
const res = await postAuthenticatedRequest<Image, SubmitData>({
tenant: tenantConfig?.id,
url: `/app/contributions/${contributionGUID}/images`,
data: submitData,
Loading