Skip to content

Commit 7c9c465

Browse files
committed
feat(web): add debounce, skeleton while loading
1 parent 3e2b100 commit 7c9c465

File tree

1 file changed

+71
-30
lines changed

1 file changed

+71
-30
lines changed

web/src/pages/DisputeTemplateView.tsx

Lines changed: 71 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import { executeActions } from "@kleros/kleros-sdk/src/dataMappings/executeActio
99
import { populateTemplate } from "@kleros/kleros-sdk/src/dataMappings/utils/populateTemplate";
1010
import { Answer, DisputeDetails } from "@kleros/kleros-sdk/src/dataMappings/utils/disputeDetailsTypes";
1111
import { alchemyApiKey } from "context/Web3Provider";
12+
import { useDebounce } from "react-use";
13+
import Skeleton from "react-loading-skeleton";
1214

1315
const Container = styled.div`
1416
width: 50%;
@@ -110,57 +112,96 @@ const LongText = styled.div`
110112
width: auto;
111113
`;
112114

113-
const DisputeTemplateView: React.FC = () => {
115+
const DisputeTemplateView = () => {
114116
const [disputeDetails, setDisputeDetails] = useState<DisputeDetails | undefined>(undefined);
115117
const [disputeTemplateInput, setDisputeTemplateInput] = useState<string>("");
116118
const [dataMappingsInput, setDataMappingsInput] = useState<string>("");
117-
118119
const [arbitrator, setArbitrator] = useState("");
119120
const [arbitrable, setArbitrable] = useState("");
120121
const [arbitrableDisputeID, setArbitrableDisputeID] = useState("");
121122
const [externalDisputeID, setExternalDisputeID] = useState("");
122123
const [templateID, setTemplateID] = useState("");
123124
const [templateUri, setTemplateUri] = useState("");
124125

126+
const [debouncedArbitrator, setDebouncedArbitrator] = useState(arbitrator);
127+
const [debouncedArbitrable, setDebouncedArbitrable] = useState(arbitrable);
128+
const [debouncedArbitrableDisputeID, setDebouncedArbitrableDisputeID] = useState(arbitrableDisputeID);
129+
const [debouncedExternalDisputeID, setDebouncedExternalDisputeID] = useState(externalDisputeID);
130+
const [debouncedTemplateID, setDebouncedTemplateID] = useState(templateID);
131+
const [debouncedTemplateUri, setDebouncedTemplateUri] = useState(templateUri);
132+
const [loading, setLoading] = useState(false);
133+
134+
useDebounce(() => setDebouncedArbitrator(arbitrator), 350, [arbitrator]);
135+
useDebounce(() => setDebouncedArbitrable(arbitrable), 350, [arbitrable]);
136+
useDebounce(() => setDebouncedArbitrableDisputeID(arbitrableDisputeID), 350, [arbitrableDisputeID]);
137+
useDebounce(() => setDebouncedExternalDisputeID(externalDisputeID), 350, [externalDisputeID]);
138+
useDebounce(() => setDebouncedTemplateID(templateID), 350, [templateID]);
139+
useDebounce(() => setDebouncedTemplateUri(templateUri), 350, [templateUri]);
140+
125141
useEffect(() => {
126142
configureSDK({ apiKey: alchemyApiKey });
127143

128-
const initialContext = {
129-
arbitrator: arbitrator,
130-
arbitrable: arbitrable,
131-
arbitrableDisputeID: parseInt(arbitrableDisputeID),
132-
externalDisputeID: parseInt(externalDisputeID),
133-
templateID: parseInt(templateID),
134-
templateUri: templateUri,
135-
};
144+
let isFetchDataScheduled = false;
145+
146+
const scheduleFetchData = () => {
147+
if (!isFetchDataScheduled) {
148+
isFetchDataScheduled = true;
136149

137-
if (!disputeTemplateInput || !dataMappingsInput) return;
150+
setLoading(true);
138151

139-
const fetchData = async () => {
140-
try {
141-
const parsedMappings = JSON.parse(dataMappingsInput);
142-
const data = await executeActions(parsedMappings, initialContext);
143-
const finalDisputeDetails = populateTemplate(disputeTemplateInput, data);
144-
setDisputeDetails(finalDisputeDetails);
145-
console.log("finalTemplate: ", finalDisputeDetails);
146-
} catch (e) {
147-
console.error(e);
148-
setDisputeDetails(undefined);
152+
setTimeout(() => {
153+
const initialContext = {
154+
arbitrator: debouncedArbitrator,
155+
arbitrable: debouncedArbitrable,
156+
arbitrableDisputeID: debouncedArbitrableDisputeID,
157+
externalDisputeID: debouncedExternalDisputeID,
158+
templateID: debouncedTemplateID,
159+
templateUri: debouncedTemplateUri,
160+
};
161+
162+
const fetchData = async () => {
163+
try {
164+
const parsedMappings = JSON.parse(dataMappingsInput);
165+
const data = await executeActions(parsedMappings, initialContext);
166+
const finalDisputeDetails = populateTemplate(disputeTemplateInput, data);
167+
setDisputeDetails(finalDisputeDetails);
168+
} catch (e) {
169+
console.error(e);
170+
setDisputeDetails(undefined);
171+
} finally {
172+
setLoading(false);
173+
}
174+
};
175+
176+
fetchData();
177+
178+
isFetchDataScheduled = false;
179+
}, 350);
149180
}
150181
};
151182

152-
fetchData();
183+
if (
184+
disputeTemplateInput ||
185+
dataMappingsInput ||
186+
debouncedArbitrator ||
187+
debouncedArbitrable ||
188+
debouncedArbitrableDisputeID ||
189+
debouncedExternalDisputeID ||
190+
debouncedTemplateID ||
191+
debouncedTemplateUri
192+
) {
193+
scheduleFetchData();
194+
}
153195
}, [
154196
disputeTemplateInput,
155197
dataMappingsInput,
156-
arbitrable,
157-
arbitrator,
158-
arbitrableDisputeID,
159-
externalDisputeID,
160-
templateID,
161-
templateUri,
198+
debouncedArbitrator,
199+
debouncedArbitrable,
200+
debouncedArbitrableDisputeID,
201+
debouncedExternalDisputeID,
202+
debouncedTemplateID,
203+
debouncedTemplateUri,
162204
]);
163-
164205
return (
165206
<>
166207
<StyledHeader>Dispute Preview</StyledHeader>
@@ -238,7 +279,7 @@ const DisputeTemplateView: React.FC = () => {
238279
placeholder="Enter data mappings"
239280
/>
240281
</LongText>
241-
<Overview disputeDetails={disputeDetails} />
282+
{loading ? <Skeleton width={300} /> : <Overview disputeDetails={disputeDetails} />}
242283
</LongTextSections>
243284
</>
244285
);

0 commit comments

Comments
 (0)