Skip to content

Commit

Permalink
feat: generate and download qr code with apis (#19)
Browse files Browse the repository at this point in the history
## Description

This PR adds support for generating QR codes with APIs and the ability
to download them

<!-- Add a description of the changes that this PR introduces and the
files that
are the most critical to review. -->

---

### Author Checklist

*All items are required. Please add a note to the item if the item is
not applicable and
please add links to any relevant follow up issues.*

I have...

- [x] included the correct [type
prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json)
  in the PR title
- [ ] targeted the correct branch
- [ ] provided a link to the relevant issue or specification
- [ ] reviewed "Files changed" and left comments if necessary
- [ ] confirmed all CI checks have passed

### Reviewers Checklist

*All items are required. Please add a note if the item is not applicable
and please add
your handle next to the items reviewed if you only reviewed selected
items.*

I have...

- [ ] confirmed the
correct [type
prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json)
in the PR title
- [ ] confirmed all author checklist items have been addressed
  • Loading branch information
Alessandro Mazzon authored Oct 10, 2023
1 parent 8fe291f commit b490cb7
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 26 deletions.
106 changes: 80 additions & 26 deletions app/creator/events/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,60 @@ import useCustomLazyQuery from "@/hooks/graphql/useCustomLazyQuery";
import GetEventById from "@/services/graphql/queries/bondscape/GetEventById";
import Skeleton from "react-loading-skeleton";
import { Dialog } from "primereact/dialog";
import { QRCodeSVG } from "qrcode.react";
import { Button } from "primereact/button";
import GetQrCode from "@/services/axios/requests/GetQrCode";
import { PuffLoader } from "react-spinners";
import { toast } from "react-toastify";
import GetEventJoinLink from "@/services/axios/requests/GetEventJoinLink";

export default function EventDetails({ params }: { params: any }) {
const [selectedEvent, setSelectedEvent] = useState<Event>();
const [eventQrCode, setEventQrCode] = useState("");
const [generatingQr, setGeneratingQr] = useState(false);
const [qrCodeVisible, setQrCodeVisible] = useState(false);
const [isMobile, isMd] = useBreakpoints();
const router = useRouter();
const [getEventById] = useCustomLazyQuery<GQLEventsResult>(GetEventById);
const { getEventPeriodExtended } = useFormatDateToTZ();
const { googlePlace } = useGetGooglePlace(selectedEvent?.googlePlaceId);

const generateQrCode = useCallback(async (url: string) => {
const result = await GetQrCode(url, "url");
if (result.isOk()) {
setEventQrCode(result.value.url);
}
}, []);

const toDataURL = useCallback(async () => {
setGeneratingQr(true);
try {
const response = await fetch(eventQrCode);
const blob = await response.blob();
return URL.createObjectURL(blob);
} finally {
setGeneratingQr(false);
}
}, [eventQrCode]);

const saveQrCode = useCallback(async () => {
const a = document.createElement("a");
a.href = await toDataURL();
a.download = `bondscape_${selectedEvent?.name}_qr_code.png`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}, [selectedEvent?.name, toDataURL]);

useEffect(() => {
if (selectedEvent) {
GetEventJoinLink(selectedEvent.id).then((result) => {
if (result.isOk()) {
generateQrCode(result.value);
}
});
}
}, [generateQrCode, selectedEvent]);

const loadEvent = useCallback(
async (eventId: string) => {
const result = await getEventById({
Expand Down Expand Up @@ -277,37 +319,49 @@ export default function EventDetails({ params }: { params: any }) {
>
<div className="flex flex-1 flex-col items-center justify-center">
<div className="p-2.5 rounded-[8px] bg-white">
<QRCodeSVG
value={selectedEvent?.detailsLink ?? ""}
size={158}
fgColor={"#8358F9"}
level={"H"}
imageSettings={{
src: "/qrCodeLogo.png",
width: 67,
height: 67,
excavate: false,
}}
/>
{eventQrCode ? (
<Image
alt={"Qr code"}
src={eventQrCode}
width={158}
height={158}
/>
) : (
<PuffLoader color={"#A579FF"} />
)}
</div>
<div className="flex flex-1 flex-col gap-[40px] items-center">
<div className="text-xl font-semibold text-bondscape-text_neutral_900 mt-6">
{selectedEvent?.name ?? <Skeleton width={500} />}
</div>
{selectedEvent && (
<Button
outlined
className="w-[432px] justify-center font-semibold"
pt={{
label: {
className: "font-semibold",
},
}}
label={"Copy Link"}
onClick={() => {
navigator.clipboard.writeText(selectedEvent.detailsLink);
}}
/>
<div className="flex flex-col gap-4">
<Button
outlined
className="w-[432px] justify-center font-semibold"
pt={{
label: {
className: "font-semibold",
},
}}
label={"Copy Link"}
onClick={() => {
navigator.clipboard.writeText(selectedEvent.detailsLink);
toast("Link copied to clipboard!");
}}
/>
<Button
loading={generatingQr}
className="w-[432px] justify-center font-semibold"
pt={{
label: {
className: "font-semibold",
},
}}
label={"Download QR Code"}
onClick={() => saveQrCode()}
/>
</div>
)}
</div>
</div>
Expand Down
11 changes: 11 additions & 0 deletions app/services/axios/requests/GetEventJoinLink/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { ResultAsync } from "neverthrow";
import axiosInstance from "../../index";

const GetEventJoinLink = (eventId: string): ResultAsync<string, Error> => {
return ResultAsync.fromPromise(
axiosInstance.get(`/events/${eventId}/links/join`),
(e: any) => e ?? Error("Error getting the link"),
).map((response) => response.data);
};

export default GetEventJoinLink;
22 changes: 22 additions & 0 deletions app/services/axios/requests/GetQrCode/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { ResultAsync } from "neverthrow";
import axiosInstance from "../../index";

/**
* Users can generate a QR code for any given link.
*/

const GetQrCode = (
url: string,
type: "url" | "image",
): ResultAsync<any, Error> => {
return ResultAsync.fromPromise(
axiosInstance.get(`/qrcode?url=${url}`, {
headers: {
Accept: type === "url" ? "application/json" : "image/*",
},
}),
(e: any) => e ?? Error("Error getting the qr code"),
).map((response) => response.data);
};

export default GetQrCode;

0 comments on commit b490cb7

Please sign in to comment.