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

Feature/direct exchange button #355

Merged
merged 4 commits into from
Jan 31, 2025
Merged
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
36 changes: 20 additions & 16 deletions src/api/services/exchangeRequestService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,26 @@ const submitExchangeRequest = async (requests: Map<number, CreateRequestData>, u

if (urgentMessage !== "") formData.append("urgentMessage", urgentMessage);

return fetch(
`${api.BACKEND_URL}/exchange/${isDirectExchange(requests.values()) ? "direct/" : "marketplace/"}`,
{
method: "POST",
credentials: "include",
headers: {
"X-CSRFToken": api.getCSRFToken(),
},
body: formData
},
).then(async (res) => {
const json = await res.json();
return json;
}).catch((e) => {
console.error(e);
});
try {
const res = await fetch(
`${api.BACKEND_URL}/exchange/${isDirectExchange(requests.values()) ? "direct/" : "marketplace/"}`,
{
method: "POST",
credentials: "include",
headers: {
"X-CSRFToken": api.getCSRFToken(),
},
body: formData
}
);

return res;
}
catch (error)
{
console.error(error);
throw new Error("Network error");
}
}

const retrieveMarketplaceRequest = async (url: string): Promise<MarketplaceRequest[]> => {
Expand Down
6 changes: 3 additions & 3 deletions src/components/exchange/requests/issue/CustomizeRequest.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ export const CustomizeRequest = ({

const submitRequest = async (urgentMessage: string) => {
setSubmittingRequest(true);
const json = await exchangeRequestService.submitExchangeRequest(requests, urgentMessage);
const res = await exchangeRequestService.submitExchangeRequest(requests, urgentMessage);

if (json.success) {
if (res.ok) {
setPreviewingForm(false);
toast({
title: 'Pedido submetido com sucesso!',
Expand All @@ -43,7 +43,7 @@ export const CustomizeRequest = ({
setPreviewingForm(false);
toast({
title: 'Erro ao submeter o pedido.',
description: exchangeErrorToText[json.error]
description: exchangeErrorToText[(await res.json())["error"]]
});
}

Expand Down
54 changes: 33 additions & 21 deletions src/components/exchange/requests/view/cards/RequestCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ import { Button } from "../../../../ui/button";
import { Card, CardContent, CardFooter } from "../../../../ui/card";
import { Checkbox } from "../../../../ui/checkbox";
import { Separator } from "../../../../ui/separator";
import exchangeRequestService from "../../../../../api/services/exchangeRequestService";
import { ListRequestChanges } from "./ListRequestChanges";
import ExchangeRequestCommonContext from "../../../../../contexts/ExchangeRequestCommonContext";
import { CommonCardHeader } from "./CommonCardHeader";
import ConflictsContext from "../../../../../contexts/ConflictsContext";
import { ExchangeOption } from "../../../../../@types";
import { useToast } from "../../../../ui/use-toast";
import { exchangeErrorToText } from "../../../../../utils/error";
import useMarketplaceAcceptExchange from "../../../../../hooks/useMarketplaceAcceptExchange";
import { MoonLoader } from "react-spinners";

export const RequestCard = () => {
const {
Expand All @@ -20,6 +22,9 @@ export const RequestCard = () => {
const [hovered, setHovered] = useState<boolean>(false);

const { isConflictSevere } = useContext(ConflictsContext);
const { toast } = useToast();

const { trigger: requestExchangeProposal, isMutating: isProcessingExchangeProposal} = useMarketplaceAcceptExchange(request, selectedOptions);

useEffect(() => {
if (chosenRequest?.id !== request.id) {
Expand All @@ -42,26 +47,30 @@ export const RequestCard = () => {
const submitExchange = async (e) => {
e.preventDefault();

const exchangeRequests = new Map();
for (const option of request.options) {
if (selectedOptions.get(option.course_info.acronym)) {
exchangeRequests.set(
option.course_info.id,
{
courseUnitId: option.course_info.id,
courseUnitName: option.course_info.name,
classNameRequesterGoesFrom: (option as ExchangeOption).class_issuer_goes_from.name,
classNameRequesterGoesTo: (option as ExchangeOption).class_issuer_goes_to.name,
other_student: {
name: request.issuer_name,
mecNumber: request.issuer_nmec
}
}
);
try {
const response = await requestExchangeProposal();
if (response && response.ok) {
toast({
title: "Troca proposta com sucesso!",
description: "A proposta de troca foi realizada com sucesso.",
variant: "default",
});
}
else {
toast({
title: "Erro ao propor troca.",
description: exchangeErrorToText[(await response.json())["error"]],
variant: "destructive",
});
}
}

await exchangeRequestService.submitExchangeRequest(exchangeRequests);
catch (error) {
toast({
title: "Erro ao propor a troca.",
description: `Houve um erro desconhecido: ${error.message}`,
variant: "destructive",
});
}
};

return <>
Expand Down Expand Up @@ -114,7 +123,10 @@ export const RequestCard = () => {
className={isConflictSevere ? "disabled:bg-red-400" : "success-button hover:bg-white"}
disabled={isConflictSevere}
>
Propôr troca
{ isProcessingExchangeProposal
? <MoonLoader size={20} />
: <p>Propôr troca</p>
}
</Button>
</form>
</div>
Expand Down
47 changes: 47 additions & 0 deletions src/hooks/useMarketplaceAcceptExchange.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { useMemo } from "react";
import useSWRMutation from "swr/mutation";
import { DirectExchangeRequest, ExchangeOption, MarketplaceRequest } from "../@types";
import exchangeRequestService from "../api/services/exchangeRequestService";

/**
* This is used to submit a exchange proposal in the marketplace.
* We need this hook to improve the readibility of the code to show a loading state and so on.
*/
export default (request: MarketplaceRequest | DirectExchangeRequest, selectedOptions: Map<string, boolean>) => {
const submit = async () => {
const exchangeRequests = new Map();
for (const option of request.options) {
if (selectedOptions.get(option.course_info.acronym)) {
exchangeRequests.set(
option.course_info.id,
{
courseUnitId: option.course_info.id,
courseUnitName: option.course_info.name,
classNameRequesterGoesTo: (option as ExchangeOption).class_issuer_goes_from.name,
classNameRequesterGoesFrom: (option as ExchangeOption).class_issuer_goes_to.name,
other_student: {
name: request.issuer_name,
mecNumber: request.issuer_nmec
}
}
);
}
}

return exchangeRequestService.submitExchangeRequest(exchangeRequests, "");
}

const { data, error, trigger, isMutating } = useSWRMutation(
`${request.id}`,
submit
);
const directExchangeValid = useMemo(() => data ? data : null, [data]);

return {
directExchangeValid,
error,
trigger,
isMutating
};
};