diff --git a/TODO b/TODO
index ef2adc9b1..484f346d0 100644
--- a/TODO
+++ b/TODO
@@ -1,8 +1,5 @@
hype should impact the magnitude of the home court advantage
-support sorting mobile trade tables (like saved trades, trading block)
-- or have toggle to switch between them?
-
embed facesjs ui
- what to do about all the dependencies?
- could load async
diff --git a/src/ui/hooks/useTradeOffersSwitch.tsx b/src/ui/hooks/useTradeOffersSwitch.tsx
new file mode 100644
index 000000000..4bee2b83c
--- /dev/null
+++ b/src/ui/hooks/useTradeOffersSwitch.tsx
@@ -0,0 +1,37 @@
+import { useMemo } from "react";
+import useLocalStorageState from "use-local-storage-state";
+
+const useTradeOffersSwitch = () => {
+ const [value, setValue] = useLocalStorageState<"table" | "list">(
+ "tradeOffersOverride",
+ {
+ defaultValue: "list",
+ },
+ );
+
+ const toggle = useMemo(
+ () => (
+
+ ),
+ [setValue, value],
+ );
+
+ return {
+ toggle: window.mobile ? toggle : null,
+ value: window.mobile ? value : "table",
+ };
+};
+
+export default useTradeOffersSwitch;
diff --git a/src/ui/views/SavedTrades.tsx b/src/ui/views/SavedTrades.tsx
index 09bddcc35..9ccf5e4f1 100644
--- a/src/ui/views/SavedTrades.tsx
+++ b/src/ui/views/SavedTrades.tsx
@@ -11,6 +11,7 @@ import {
playerScore,
} from "./TradingBlock";
import { Dropdown } from "react-bootstrap";
+import useTradeOffersSwitch from "../hooks/useTradeOffersSwitch";
const SavedTrades = (props: View<"savedTrades">) => {
const {
@@ -30,6 +31,8 @@ const SavedTrades = (props: View<"savedTrades">) => {
const { teamInfoCache } = useLocalPartial(["teamInfoCache"]);
+ const tradeOffersSwitch = useTradeOffersSwitch();
+
if (spectator) {
return You're not allowed to make trades in spectator mode.
;
}
@@ -102,9 +105,7 @@ const SavedTrades = (props: View<"savedTrades">) => {
pages.
-
- Clear
-
+ Clear
{
@@ -129,8 +130,12 @@ const SavedTrades = (props: View<"savedTrades">) => {
- {offers.length === 0 ? No saved trades
: null}
-
+ {offers.length === 0 ? (
+
No saved trades
+ ) : (
+ tradeOffersSwitch.toggle
+ )}
+ {tradeOffersSwitch.value === "table" ? (
) => {
salaryCap={salaryCap}
salaryCapType={salaryCapType}
/>
-
-
-
- {offers.map(offer => {
- return (
-
{
- handleNegotiate(offer);
- }}
- salaryCap={salaryCap}
- salaryCapType={salaryCapType}
- teamInfo={teamInfoCache[offer.tid]}
- hideTopTeamOvrs
- {...offer}
- >
-
- {offer.summary.teams.map((t, j) => {
- const missingKey = j === 0 ? "missing" : "missingUser";
- return (
-
-
-
- );
- })}
-
-
- );
- })}
-
+ ) : (
+ <>
+ {offers.map((offer, i) => {
+ return (
+ {
+ handleNegotiate(offer);
+ }}
+ salaryCap={salaryCap}
+ salaryCapType={salaryCapType}
+ teamInfo={teamInfoCache[offer.tid]}
+ hideTopTeamOvrs
+ first={i === 0}
+ {...offer}
+ >
+
+ {offer.summary.teams.map((t, j) => {
+ const missingKey = j === 0 ? "missing" : "missingUser";
+ return (
+
+
+
+ );
+ })}
+
+
+ );
+ })}
+ >
+ )}
>
);
};
diff --git a/src/ui/views/TradeProposals.tsx b/src/ui/views/TradeProposals.tsx
index 21c7bd4ba..2c9c4ba0f 100644
--- a/src/ui/views/TradeProposals.tsx
+++ b/src/ui/views/TradeProposals.tsx
@@ -12,6 +12,7 @@ import {
} from "./TradingBlock";
import { useEffect, useState } from "react";
import { ActionButton } from "../components";
+import useTradeOffersSwitch from "../hooks/useTradeOffersSwitch";
const TradeProposals = (props: View<"tradeProposals">) => {
const {
@@ -47,6 +48,8 @@ const TradeProposals = (props: View<"tradeProposals">) => {
const [refreshing, setRefreshing] = useState(false);
+ const tradeOffersSwitch = useTradeOffersSwitch();
+
if (spectator) {
return You're not allowed to make trades in spectator mode.
;
}
@@ -119,7 +122,6 @@ const TradeProposals = (props: View<"tradeProposals">) => {
here every 10 games.
{
setRefreshing(true);
await toWorker("main", "incrementTradeProposalsSeed", undefined);
@@ -131,7 +133,8 @@ const TradeProposals = (props: View<"tradeProposals">) => {
>
Refresh trade proposals
-
+ {tradeOffersSwitch.toggle}
+ {tradeOffersSwitch.value === "table" ? (
) => {
salaryCap={salaryCap}
salaryCapType={salaryCapType}
/>
-
-
-
- {filteredOffers.map(offer => {
- return (
-
{
- handleNegotiate(offer);
- }}
- onRemove={() => {
- const tid = offer.tid;
- setRemovedTids(prevTids => [...prevTids, tid]);
- }}
- salaryCap={salaryCap}
- salaryCapType={salaryCapType}
- teamInfo={teamInfoCache[offer.tid]}
- hideTopTeamOvrs
- {...offer}
- >
-
- {offer.summary.teams.map((t, j) => {
- return (
-
-
-
- );
- })}
-
-
- );
- })}
-
+ ) : (
+ <>
+ {filteredOffers.map((offer, i) => {
+ return (
+ {
+ handleNegotiate(offer);
+ }}
+ onRemove={() => {
+ const tid = offer.tid;
+ setRemovedTids(prevTids => [...prevTids, tid]);
+ }}
+ salaryCap={salaryCap}
+ salaryCapType={salaryCapType}
+ teamInfo={teamInfoCache[offer.tid]}
+ hideTopTeamOvrs
+ first={i === 0}
+ {...offer}
+ >
+
+ {offer.summary.teams.map((t, j) => {
+ return (
+
+
+
+ );
+ })}
+
+
+ );
+ })}
+ >
+ )}
>
);
};
diff --git a/src/ui/views/TradingBlock.tsx b/src/ui/views/TradingBlock.tsx
index 0bb1b1bb9..b645e342b 100644
--- a/src/ui/views/TradingBlock.tsx
+++ b/src/ui/views/TradingBlock.tsx
@@ -20,6 +20,7 @@ import {
import { wrappedPlayerNameLabels } from "../components/PlayerNameLabels";
import { MissingAssets, OvrChange } from "./Trade/Summary";
import type { MissingAsset } from "../../worker/views/savedTrades";
+import useTradeOffersSwitch from "../hooks/useTradeOffersSwitch";
export type OfferType = Awaited<
ReturnType<(typeof api)["main"]["getTradingBlockOffers"]>
@@ -31,6 +32,7 @@ export type OfferType = Awaited<
type OfferProps = {
children: ReactNode;
+ first: boolean;
hideTopTeamOvrs?: boolean;
onNegotiate: () => void;
onRemove?: () => void;
@@ -101,7 +103,7 @@ const OfferPlayers = ({
});
let footer;
- if (sumContracts !== 0) {
+ if (sumContracts !== 0 && players.length > 1) {
footer = [];
// Total text is too distracting, and it's usually a small number of players
/*footer[0] = (
@@ -137,6 +139,7 @@ export const Offer = (props: OfferProps) => {
children,
dpids,
dpidsUser,
+ first,
hideTopTeamOvrs,
onNegotiate,
onRemove,
@@ -163,7 +166,7 @@ export const Offer = (props: OfferProps) => {
}
return (
-
+
-
+ {state.offers.length > 0 ? (
+
{tradeOffersSwitch.toggle}
+ ) : null}
+
+ {tradeOffersSwitch.value === "table" ? (
-
-
-
- {state.offers.map((offer, i) => {
- return (
-
{
- handleNegotiate(offer.tid, offer.pids, offer.dpids);
- }}
- onRemove={() => {
- handleRemove(i);
- }}
- salaryCap={salaryCap}
- salaryCapType={salaryCapType}
- teamInfo={teamInfoCache[offer.tid]}
- {...offer}
- >
- {offer.picks.length > 0 || offer.players.length > 0 ? (
-
- {offer.players.length > 0 ? (
-
-
- {(offer.missing && offer.missing.length > 0) ||
- offer.willing === false ? (
-
-
-
- ) : null}
-
- ) : null}
- {offer.picks.length > 0 ? (
-
-
-
-
- Draft Picks |
-
-
-
- {offer.picks.map(pick => (
-
-
-
- |
+ ) : (
+ <>
+ {state.offers.map((offer, i) => {
+ return (
+ {
+ handleNegotiate(offer.tid, offer.pids, offer.dpids);
+ }}
+ onRemove={() => {
+ handleRemove(i);
+ }}
+ salaryCap={salaryCap}
+ salaryCapType={salaryCapType}
+ teamInfo={teamInfoCache[offer.tid]}
+ first={i === 0}
+ {...offer}
+ >
+ {offer.picks.length > 0 || offer.players.length > 0 ? (
+
+ {offer.players.length > 0 ? (
+
+
+ {(offer.missing && offer.missing.length > 0) ||
+ offer.willing === false ? (
+
+
+
+ ) : null}
+
+ ) : null}
+ {offer.picks.length > 0 ? (
+
+
+
+
+ Draft Picks |
- ))}
-
-
-
- ) : null}
-
- ) : (
- Nothing.
- )}
-
- );
- })}
-
+
+
+ {offer.picks.map(pick => (
+
+
+
+ |
+
+ ))}
+
+
+
+ ) : null}
+
+ ) : (
+ Nothing.
+ )}
+
+ );
+ })}
+ >
+ )}
>
);
};
diff --git a/src/worker/api/index.ts b/src/worker/api/index.ts
index 22674bd6b..06eda4ea4 100644
--- a/src/worker/api/index.ts
+++ b/src/worker/api/index.ts
@@ -4306,6 +4306,10 @@ const clearTrade = async (
await toUI("realtimeUpdate", []);
};
+const clearTradingBlock = async () => {
+ await idb.cache.savedTradingBlock.clear();
+};
+
const createTrade = async (teams: TradeTeams) => {
await trade.create(teams);
await toUI("realtimeUpdate", []);
@@ -4495,6 +4499,7 @@ export default {
clearSavedTrades,
clearTeamNotes,
clearTrade,
+ clearTradingBlock,
clearWatchList,
countNegotiations,
createLeague,