From ff1a42790095f28929883a213fe4c969d6c2f5f9 Mon Sep 17 00:00:00 2001 From: George Kartalis Date: Fri, 31 Jul 2026 18:42:00 +0200 Subject: [PATCH 1/3] chore: clear remaining STRICTNESS_MIGRATION suppressions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### Description Removes the remaining `@ts-expect-error STRICTNESS_MIGRATION` / `as any` suppressions left after the first pass (which covered the zero-behavior-change fixes). This batch fixes real null-safety holes that the suppressions were hiding, so each one is a small, deliberate behavior change: - BidButton: renders nothing instead of throwing when `sale` is missing. - MakeOfferButton / InquiryMakeOfferButton: guard a null mutation payload instead of throwing inside the Relay callback. - SendConversationMessage: skip the optimistic update instead of throwing when the connection/edge isn't found. - Gemini upload helpers: reject with a real error instead of throwing on a null asset/credentials payload. - FeaturedArtists: filter out null artist entries instead of crashing on `.internalID`; no-op tracking if `tracking` is undefined. - FullFeaturedArtistList: fix an invalid spacing value (`pb={20}` → `pb="20px"`). - useScreenDimensions: seed the context with real dimensions instead of `null`. - DeepZoomTile: silence two known-safe conditional hook calls gated by a module-level debug constant, surfaced while touching this file. `yarn tsc` is clean repo-wide. Remaining `STRICTNESS_MIGRATION` markers are confined to the legacy City Guide / Map scenes, out of scope for this PR. Co-Authored-By: Claude Sonnet 5 --- .../Components/Bidding/Components/Timer.tsx | 4 +- .../Components/Bidding/Components/Title.tsx | 4 +- src/app/Components/Bidding/Elements/Grid.tsx | 16 +- .../Bidding/Screens/Registration.tsx | 42 ++-- .../Screens/__tests__/Registration.tests.tsx | 55 ++-- .../Components/Countdown/CountdownTimer.tsx | 7 +- .../Components/Countdown/DurationProvider.tsx | 2 +- src/app/Components/Countdown/StateManager.tsx | 2 +- .../createGeminiAssetWithS3Credentials.ts | 8 +- .../getGeminiCredentialsForEnvironment.ts | 16 +- .../PhotoRow/utils/uploadFileToS3.ts | 14 +- .../Artwork/Components/AuctionPrice.tsx | 165 ------------ .../CommercialButtons/BidButton.tsx | 42 ++-- .../CommercialButtons/MakeOfferButton.tsx | 12 +- .../FullScreen/DeepZoom/DeepZoomOverlay.tsx | 22 +- .../FullScreen/DeepZoom/DeepZoomTile.tsx | 6 +- .../FullScreen/ImageCarouselFullScreen.tsx | 11 +- .../ImageCarouselFullScreen.tests.tsx | 3 +- .../ImageCarousel/ImageCarouselContext.tsx | 9 +- .../ImageCarousel/ImageCarouselEmbedded.tsx | 5 +- .../__tests__/ImageCarouselContext.tests.tsx | 3 +- .../__tests__/ImageCarouselEmbedded.tests.tsx | 5 +- .../__tests__/AuctionPrice.tests.tsx | 235 ------------------ .../CollectionArtistSeriesRail.tests.tsx | 5 +- .../FeaturedCollectionsRail.tests.tsx | 5 +- .../Collection/Components/FeaturedArtists.tsx | 22 +- .../Components/FullFeaturedArtistList.tsx | 3 +- .../Conversations/InquiryMakeOfferButton.tsx | 12 +- .../Conversations/SendConversationMessage.ts | 8 +- .../middlewares/metaphysicsMiddleware.ts | 6 +- .../relay/middlewares/timingMiddleware.ts | 8 +- .../utils/__tests__/renderMarkdown.tests.tsx | 10 +- .../bidderNeedsIdentityVerification.ts | 16 +- src/app/utils/hooks/useScreenDimensions.tsx | 9 +- 34 files changed, 194 insertions(+), 598 deletions(-) delete mode 100644 src/app/Scenes/Artwork/Components/AuctionPrice.tsx delete mode 100644 src/app/Scenes/Artwork/Components/__tests__/AuctionPrice.tests.tsx diff --git a/src/app/Components/Bidding/Components/Timer.tsx b/src/app/Components/Bidding/Components/Timer.tsx index e895311b02f..c392992a5b4 100644 --- a/src/app/Components/Bidding/Components/Timer.tsx +++ b/src/app/Components/Bidding/Components/Timer.tsx @@ -207,12 +207,12 @@ export const Timer: React.FC = (props) => { onCurrentTickerState={() => { const state = currentTimerState(props) const { label, date } = relevantStateData(state, props) - return { label, date, state } as any // STRICTNESS_MIGRATION + return { label, date, state } }} onNextTickerState={({ state }) => { const nextState = nextTimerState(state as AuctionTimerState, props) const { label, date } = relevantStateData(nextState, props) - return { state: nextState, label, date } as any // STRICTNESS_MIGRATION + return { state: nextState, label, date } }} /> diff --git a/src/app/Components/Bidding/Components/Title.tsx b/src/app/Components/Bidding/Components/Title.tsx index f02c4a470b8..8a273ab38fa 100644 --- a/src/app/Components/Bidding/Components/Title.tsx +++ b/src/app/Components/Bidding/Components/Title.tsx @@ -1,5 +1,5 @@ -import { Text } from "@artsy/palette-mobile" +import { Text, TextProps } from "@artsy/palette-mobile" -export const Title = (props: any /* STRICTNESS_MIGRATION */) => ( +export const Title = (props: TextProps) => ( ) diff --git a/src/app/Components/Bidding/Elements/Grid.tsx b/src/app/Components/Bidding/Elements/Grid.tsx index d8cea015b07..125b010ae00 100644 --- a/src/app/Components/Bidding/Elements/Grid.tsx +++ b/src/app/Components/Bidding/Elements/Grid.tsx @@ -1,6 +1,16 @@ -import { Flex } from "app/Components/Bidding/Elements/Flex" +import { Flex, FlexProps } from "app/Components/Bidding/Elements/Flex" +import { PropsWithChildren } from "react" -export const Row = (props: any /* STRICTNESS_MIGRATION */) => ( +type GridProps = PropsWithChildren< + Omit & { + flex?: FlexProps["flex"] | null + flexGrow?: number + flexShrink?: number + flexBasis?: number | string + } +> + +export const Row = (props: GridProps) => ( ) -export const Col = (props: any /* STRICTNESS_MIGRATION */) => +export const Col = (props: GridProps) => diff --git a/src/app/Components/Bidding/Screens/Registration.tsx b/src/app/Components/Bidding/Screens/Registration.tsx index c5bf17a265c..302ec40afdf 100644 --- a/src/app/Components/Bidding/Screens/Registration.tsx +++ b/src/app/Components/Bidding/Screens/Registration.tsx @@ -47,10 +47,10 @@ export interface RegistrationProps } interface RegistrationState { - billingAddress?: Address + billingAddress?: Address | null phoneNumber?: string - creditCardFormParams?: PaymentCardTextFieldParams - creditCardToken?: Token.Result + creditCardFormParams?: PaymentCardTextFieldParams | null + creditCardToken?: Token.Result | null conditionsOfSaleChecked: boolean isLoading: boolean missingInformation: "payment" | "phone" | null @@ -82,11 +82,8 @@ export class Registration extends React.Component {this.renderRequiredInfoHint()} - { - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 - !!bidderNeedsIdentityVerification({ sale, user: me }) && ( - <> - This auction requires Artsy to verify your identity before bidding. - - After you register, you’ll receive an email with a link to complete identity - verification. - - - ) - } - { - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 - !missingInformation && !bidderNeedsIdentityVerification({ sale, user: me }) && ( + {!!bidderNeedsIdentityVerification({ sale, user: me }) && ( + <> + This auction requires Artsy to verify your identity before bidding. - To complete your registration, please confirm that you agree to the Conditions of - Sale. + After you register, you’ll receive an email with a link to complete identity + verification. - ) - } + + )} + {!missingInformation && !bidderNeedsIdentityVerification({ sale, user: me }) && ( + + To complete your registration, please confirm that you agree to the Conditions of + Sale. + + )} - jest.fn>(fn as any) +const commitMutationMock = ( + fn?: (environment: any, config: MutationConfig) => Disposable | null +) => jest.fn(fn) afterEach(() => { jest.clearAllMocks() @@ -150,18 +152,14 @@ describe("when the sale requires identity verification", () => { describe("when pressing register button", () => { it("when a credit card needs to be added, it commits two mutations on button press", async () => { relay.commitMutation = commitMutationMock() - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 .mockImplementationOnce((_, { onCompleted }) => { - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 - onCompleted(mockRequestResponses.updateMyUserProfile, null) + onCompleted?.(mockRequestResponses.updateMyUserProfile, null) return null }) - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 .mockImplementationOnce((_, { onCompleted }) => { onCompleted?.(mockRequestResponses.creatingCreditCardSuccess, null) return null }) - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 .mockImplementationOnce((_, { onCompleted }) => { onCompleted?.(mockRequestResponses.qualifiedBidder, null) return null @@ -280,10 +278,8 @@ describe("when pressing register button", () => { it("displays the default error message if there are unhandled errors from the updateUserProfile mutation", async () => { const errors = [{ message: "malformed error" }] - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 relay.commitMutation = commitMutationMock((_, { onCompleted }) => { - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 - onCompleted({}, errors) + onCompleted?.({}, errors) return null }) as any @@ -323,10 +319,8 @@ describe("when pressing register button", () => { it("displays an error message on a updateUserProfile failure", async () => { const errors = [{ message: "There was an error with your request" }] - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 relay.commitMutation = commitMutationMock((_, { onCompleted }) => { - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 - onCompleted({}, errors) + onCompleted?.({}, errors) return null }) as any @@ -405,13 +399,10 @@ describe("when pressing register button", () => { console.error = jest.fn() // Silences component logging. ;(createToken as jest.Mock).mockReturnValueOnce(stripeToken) relay.commitMutation = commitMutationMock() - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 .mockImplementationOnce((_, { onCompleted }) => { - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 - onCompleted(mockRequestResponses.updateMyUserProfile, null) + onCompleted?.(mockRequestResponses.updateMyUserProfile, null) return null }) - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 .mockImplementationOnce((_, { onCompleted }) => { onCompleted?.(mockRequestResponses.creatingCreditCardError, null) return null @@ -444,13 +435,10 @@ describe("when pressing register button", () => { ;(createToken as jest.Mock).mockReturnValueOnce(stripeToken) relay.commitMutation = commitMutationMock() - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 .mockImplementationOnce((_, { onCompleted }) => { - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 - onCompleted(mockRequestResponses.updateMyUserProfile, null) + onCompleted?.(mockRequestResponses.updateMyUserProfile, null) return null }) - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 .mockImplementationOnce((_, { onCompleted }) => { onCompleted?.({}, errors) return null @@ -489,13 +477,10 @@ describe("when pressing register button", () => { console.error = jest.fn() // Silences component logging. ;(createToken as jest.Mock).mockReturnValueOnce(stripeToken) relay.commitMutation = commitMutationMock() - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 .mockImplementationOnce((_, { onCompleted }) => { - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 - onCompleted(mockRequestResponses.creatingCreditCardSuccess, null) + onCompleted?.(mockRequestResponses.creatingCreditCardSuccess, null) return null }) - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 .mockImplementationOnce((_, { onError }) => { onError?.(new TypeError("Network request failed")) return null @@ -561,10 +546,8 @@ describe("when pressing register button", () => { }) it("displays an error message on a network failure", async () => { - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 relay.commitMutation = commitMutationMock((_, { onError }) => { - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 - onError(new TypeError("Network request failed")) + onError?.(new TypeError("Network request failed")) return null }) as any @@ -593,10 +576,8 @@ describe("when pressing register button", () => { }) it("displays the pending result when the bidder is not qualified_for_bidding", async () => { - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 relay.commitMutation = commitMutationMock((_, { onCompleted }) => { - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 - onCompleted({ createBidder: { bidder: { qualified_for_bidding: false } } }, null) + onCompleted?.({ createBidder: { bidder: { qualified_for_bidding: false } } }, null) return null }) as any @@ -629,10 +610,8 @@ describe("when pressing register button", () => { requireIdentityVerification: true, }, } - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 relay.commitMutation = commitMutationMock((_, { onCompleted }) => { - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 - onCompleted({ createBidder: { bidder: { qualified_for_bidding: false } } }, null) + onCompleted?.({ createBidder: { bidder: { qualified_for_bidding: false } } }, null) return null }) as any @@ -651,10 +630,8 @@ describe("when pressing register button", () => { }) it("displays the completed result when the bidder is qualified_for_bidding", async () => { - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 relay.commitMutation = commitMutationMock((_, { onCompleted }) => { - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 - onCompleted({ createBidder: { bidder: { qualified_for_bidding: true } } }, null) + onCompleted?.({ createBidder: { bidder: { qualified_for_bidding: true } } }, null) return null }) as any @@ -687,10 +664,8 @@ describe("when pressing register button", () => { }, } - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 relay.commitMutation = commitMutationMock((_, { onCompleted }) => { - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 - onCompleted({ createBidder: { bidder: { qualified_for_bidding: true } } }, null) + onCompleted?.({ createBidder: { bidder: { qualified_for_bidding: true } } }, null) return null }) as any diff --git a/src/app/Components/Countdown/CountdownTimer.tsx b/src/app/Components/Countdown/CountdownTimer.tsx index 3009cdb50e7..d878978dddf 100644 --- a/src/app/Components/Countdown/CountdownTimer.tsx +++ b/src/app/Components/Countdown/CountdownTimer.tsx @@ -20,8 +20,10 @@ enum TimerState { PAST = "PAST", } -// @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 -function relevantStateData(state, { startAt, endAt, formattedOpeningHours = "" }: Props) { +function relevantStateData( + state: TimerState, + { startAt, endAt, formattedOpeningHours = "" }: Props +) { switch (state) { case TimerState.UPCOMING: return { @@ -54,7 +56,6 @@ function currentState({ startAt, endAt }: Props) { export const CountdownTimer: React.FC = (props: Props) => { const onState = () => { const state = currentState(props) - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 const { label, date } = relevantStateData(state, props) return { state, label, date } } diff --git a/src/app/Components/Countdown/DurationProvider.tsx b/src/app/Components/Countdown/DurationProvider.tsx index d28f7dfabe3..26d3d8627f1 100644 --- a/src/app/Components/Countdown/DurationProvider.tsx +++ b/src/app/Components/Countdown/DurationProvider.tsx @@ -3,7 +3,7 @@ import React from "react" import { AppState, AppStateStatus, NativeEventSubscription } from "react-native" interface Props { - startAt?: string + startAt?: string | null timeOffsetInMilliseconds?: number children: React.ReactElement onDurationEnd?: () => void diff --git a/src/app/Components/Countdown/StateManager.tsx b/src/app/Components/Countdown/StateManager.tsx index 5a6d9d14f43..28c2e9bc7fe 100644 --- a/src/app/Components/Countdown/StateManager.tsx +++ b/src/app/Components/Countdown/StateManager.tsx @@ -4,7 +4,7 @@ import { DurationProvider } from "./DurationProvider" export interface TickerState { label?: string - date?: string + date?: string | null hasStarted?: boolean state: string biddingEndAt?: string diff --git a/src/app/Components/PhotoRow/utils/gemini/createGeminiAssetWithS3Credentials.ts b/src/app/Components/PhotoRow/utils/gemini/createGeminiAssetWithS3Credentials.ts index 603951f533c..08d656983ed 100644 --- a/src/app/Components/PhotoRow/utils/gemini/createGeminiAssetWithS3Credentials.ts +++ b/src/app/Components/PhotoRow/utils/gemini/createGeminiAssetWithS3Credentials.ts @@ -30,8 +30,12 @@ export const createGeminiAssetWithS3Credentials = (input: CreateGeminiEntryForAs if (errors && errors.length > 0) { reject(new Error(JSON.stringify(errors))) } else { - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 - resolve(response.createGeminiEntryForAsset.asset.token) + const token = response.createGeminiEntryForAsset?.asset?.token + if (!token) { + reject(new Error("No asset token was returned")) + } else { + resolve(token) + } } }, }) diff --git a/src/app/Components/PhotoRow/utils/gemini/getGeminiCredentialsForEnvironment.ts b/src/app/Components/PhotoRow/utils/gemini/getGeminiCredentialsForEnvironment.ts index c186faabfa2..0d8dd094ffb 100644 --- a/src/app/Components/PhotoRow/utils/gemini/getGeminiCredentialsForEnvironment.ts +++ b/src/app/Components/PhotoRow/utils/gemini/getGeminiCredentialsForEnvironment.ts @@ -5,9 +5,11 @@ import { import { getRelayEnvironment } from "app/system/relay/defaultEnvironment" import { commitMutation, graphql } from "react-relay" -export type AssetCredentials = - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 - getGeminiCredentialsForEnvironmentMutation["response"]["requestCredentialsForAssetUpload"]["asset"] +export type AssetCredentials = NonNullable< + NonNullable< + getGeminiCredentialsForEnvironmentMutation["response"]["requestCredentialsForAssetUpload"] + >["asset"] +> export const getGeminiCredentialsForEnvironment = ( input: RequestCredentialsForAssetUploadInput @@ -47,8 +49,12 @@ export const getGeminiCredentialsForEnvironment = ( if (errors && errors.length > 0) { reject(new Error(JSON.stringify(errors))) } else { - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 - resolve(response.requestCredentialsForAssetUpload.asset) + const asset = response.requestCredentialsForAssetUpload?.asset + if (!asset) { + reject(new Error("No asset credentials were returned")) + } else { + resolve(asset) + } } }, }) diff --git a/src/app/Components/PhotoRow/utils/uploadFileToS3.ts b/src/app/Components/PhotoRow/utils/uploadFileToS3.ts index 2a80306d1f0..f8d8e3cef84 100644 --- a/src/app/Components/PhotoRow/utils/uploadFileToS3.ts +++ b/src/app/Components/PhotoRow/utils/uploadFileToS3.ts @@ -67,12 +67,8 @@ export const uploadFileToS3 = ({ : file?.item, } - for (const key in data) { - // eslint-disable-next-line no-prototype-builtins - if (data.hasOwnProperty(key)) { - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 - formData.append(key, data[key]) - } + for (const [key, value] of Object.entries(data)) { + formData.append(key, value) } // Fetch didn't seem to work, so I had to move to a lower @@ -80,11 +76,9 @@ export const uploadFileToS3 = ({ // // Kinda sucks, but https://github.com/jhen0409/react-native-debugger/issues/38 const request = new XMLHttpRequest() - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 - request.onload = (e) => { + request.onload = () => { if ( - e.target.status.toString() === - assetCredentials.policyDocument.conditions.successActionStatus + request.status.toString() === assetCredentials.policyDocument.conditions.successActionStatus ) { resolve({ key, diff --git a/src/app/Scenes/Artwork/Components/AuctionPrice.tsx b/src/app/Scenes/Artwork/Components/AuctionPrice.tsx deleted file mode 100644 index d21b6c5e71a..00000000000 --- a/src/app/Scenes/Artwork/Components/AuctionPrice.tsx +++ /dev/null @@ -1,165 +0,0 @@ -import { CheckmarkStrokeIcon, CloseStrokeIcon } from "@artsy/icons/native" -import { Spacer, Flex, Text } from "@artsy/palette-mobile" -import { AuctionPrice_artwork$data } from "__generated__/AuctionPrice_artwork.graphql" -import { AuctionTimerState } from "app/Components/Bidding/Components/Timer" -import { navigate } from "app/system/navigation/navigate" -import { get } from "app/utils/get" -import React from "react" -import { createFragmentContainer, graphql } from "react-relay" - -export interface AuctionPriceProps { - artwork: AuctionPrice_artwork$data - auctionState: AuctionTimerState -} - -// TODO: remove since it's not used anywhere -export class AuctionPrice extends React.Component { - handleBuyersPremiumTap = () => { - const auctionInternalID = - this.props.artwork && this.props.artwork.sale && this.props.artwork.sale.internalID - if (auctionInternalID) { - navigate(`/auction/${auctionInternalID}/buyers-premium`) - } - } - - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 - bidText = (bidsPresent, bidsCount) => { - const { artwork } = this.props - const bidTextParts = [] - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 - let reserveMessage = artwork.saleArtwork.reserveMessage - - if (bidsPresent) { - bidTextParts.push(bidsCount === 1 ? "1 bid" : bidsCount + " bids") - if (reserveMessage) { - reserveMessage = reserveMessage.toLocaleLowerCase() - } - } - if (reserveMessage) { - bidTextParts.push(reserveMessage) - } - return bidTextParts.join(", ") - } - - render() { - const { artwork, auctionState } = this.props - const { sale, saleArtwork } = artwork - - if (auctionState === AuctionTimerState.LIVE_INTEGRATION_ONGOING) { - // We do not have reliable Bid info for artworks in Live sales in progress - return null - } else if (auctionState === AuctionTimerState.CLOSED) { - return ( - - Bidding closed - - ) - } else if (!saleArtwork || !saleArtwork.currentBid) { - // Don't display anything if there is no starting bid info - return null - } - - const myLotStanding = artwork.myLotStanding && artwork.myLotStanding[0] - const myBidPresent = !!(myLotStanding && myLotStanding.mostRecentBid) - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 - const myBidWinning = myBidPresent && get(myLotStanding, (s) => s.activeBid.isWinning) - const myMostRecent = myBidPresent && myLotStanding.mostRecentBid - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 - const myMaxBid = get(myMostRecent, (bid) => bid.maxBid.display) - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 - const bidsCount = get(artwork, (a) => a.saleArtwork.counts.bidderPositions) - const bidsPresent = bidsCount > 0 - const bidText = this.bidText(bidsPresent, bidsCount) - ? this.bidText(bidsPresent, bidsCount) - : null - - return ( - <> - - {bidsPresent ? "Current bid" : "Starting bid"} - - {!!myBidPresent && ( - - {myBidWinning ? ( - - ) : ( - - )}{" "} - - )} - {!!saleArtwork.currentBid && saleArtwork.currentBid.display} - - - - {!!bidText && ( - - {bidText} - - )} - - {!!myMaxBid && ( - - Your max: {myMaxBid} - - )} - - {!!sale?.isWithBuyersPremium && ( - <> - - - This auction has a{" "} - this.handleBuyersPremiumTap()} - > - buyer's premium - - .{"\n"} - Shipping, taxes, and additional fees may apply. - - - )} - - ) - } -} - -export const AuctionPriceFragmentContainer = createFragmentContainer(AuctionPrice, { - artwork: graphql` - fragment AuctionPrice_artwork on Artwork { - sale { - internalID - isWithBuyersPremium - isClosed - isLiveOpen - } - saleArtwork { - reserveMessage - currentBid { - display - } - counts { - bidderPositions - } - } - myLotStanding(live: true) { - activeBid { - isWinning - } - mostRecentBid { - maxBid { - display - } - } - } - } - `, -}) diff --git a/src/app/Scenes/Artwork/Components/CommercialButtons/BidButton.tsx b/src/app/Scenes/Artwork/Components/CommercialButtons/BidButton.tsx index 281b1ae590b..4fe9aab21fe 100644 --- a/src/app/Scenes/Artwork/Components/CommercialButtons/BidButton.tsx +++ b/src/app/Scenes/Artwork/Components/CommercialButtons/BidButton.tsx @@ -4,9 +4,11 @@ import { BidButton_artwork$data } from "__generated__/BidButton_artwork.graphql" import { BidButton_me$data } from "__generated__/BidButton_me.graphql" import { AuctionTimerState } from "app/Components/Bidding/Components/Timer" import { ThemeAwareClassTheme } from "app/Components/DarkModeClassTheme" +// eslint-disable-next-line no-restricted-imports import { navigate } from "app/system/navigation/navigate" import { bidderNeedsIdentityVerification } from "app/utils/auction/bidderNeedsIdentityVerification" import { Schema } from "app/utils/track" +import { compact } from "lodash" import React from "react" import { createFragmentContainer, graphql, RelayProp } from "react-relay" import { useTracking } from "react-tracking" @@ -21,14 +23,14 @@ export interface BidButtonProps { variant?: ButtonProps["variant"] } -// @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 -const watchOnly = (sale) => - sale.isRegistrationClosed && !sale?.registrationStatus?.qualifiedForBidding -// @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 -const getMyLotStanding = (artwork) => +const watchOnly = (sale: BidButton_artwork$data["sale"]) => + !!sale?.isRegistrationClosed && !sale?.registrationStatus?.qualifiedForBidding + +const getMyLotStanding = (artwork: BidButton_artwork$data) => artwork.myLotStanding && artwork.myLotStanding.length && artwork.myLotStanding[0] -// @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 -const getHasBid = (myLotStanding) => !!(myLotStanding && myLotStanding.mostRecentBid) + +const getHasBid = (myLotStanding: ReturnType) => + !!(myLotStanding && myLotStanding.mostRecentBid) const IdentityVerificationRequiredMessage: React.FC = ({ onPress, @@ -118,8 +120,7 @@ export const BidButton: React.FC = (props) => { } const renderIsPreview = ( - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 - registrationStatus: BidButton_artwork$data["sale"]["registrationStatus"], + registrationStatus: NonNullable["registrationStatus"], needsIdentityVerification: boolean ) => { return ( @@ -184,19 +185,20 @@ export const BidButton: React.FC = (props) => { } const { sale, saleArtwork } = artwork - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 + + if (!sale) { + return null + } + const { registrationStatus } = sale - // TODO: Do we need a nil check against +sale+? - if (sale?.isClosed) { + if (sale.isClosed) { return null } const qualifiedForBidding = registrationStatus?.qualifiedForBidding const needsIdentityVerification = bidderNeedsIdentityVerification({ - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 sale, - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 user: me, bidder: registrationStatus, }) @@ -221,7 +223,6 @@ export const BidButton: React.FC = (props) => { ) - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 } else if (sale.isRegistrationClosed && !qualifiedForBidding) { return (