diff --git a/src/App.tsx b/src/App.tsx
index 18ac09d..68bf72b 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -5,7 +5,14 @@ import { Routes, Route } from "react-router-dom";
import axios from "axios";
import { initializeApp } from "firebase/app";
import { setPersistence, getAuth, inMemoryPersistence } from "firebase/auth";
-import { useLogin, LoadingScreen, AuthProvider } from "@hex-labs/core";
+import {
+ useLogin,
+ LoadingScreen,
+ AuthProvider,
+ Header,
+ HeaderItem,
+ Footer,
+} from "@hex-labs/core";
import UserData from './components/UserData';
@@ -48,12 +55,14 @@ export const App = () => {
// useAuth hook to retrieve the user's login details.
return (
-
+
+ Hexlabs Users
+
{/* Setting up our React Router to route to all the different pages we may have */}
} />
-
+
);
};
diff --git a/src/components/UserCard.tsx b/src/components/UserCard.tsx
index d552982..5086422 100644
--- a/src/components/UserCard.tsx
+++ b/src/components/UserCard.tsx
@@ -1,42 +1,204 @@
import {
Box,
+ Button,
Flex,
HStack,
+ Link,
+ Modal,
+ ModalBody,
+ ModalCloseButton,
+ ModalContent,
+ ModalFooter,
+ ModalHeader,
+ ModalOverlay,
+ Spinner,
+ Stack,
Text,
+ useDisclosure,
} from "@chakra-ui/react";
-import React from "react";
+import { apiUrl, Service } from "@hex-labs/core";
+import axios from "axios";
+import React, { useState } from "react";
type Props = {
user: any;
};
+const UserModal: React.FC<{
+ user: any;
+ isOpen: boolean;
+ onClose: () => void;
+}> = ({ user, isOpen, onClose }) => {
+ const [hexathons, setHexathons] = useState([]);
+ const [loadingHexathons, setLoadingHexathons] = useState(false);
+ const [hexathonError, setHexathonError] = useState(null);
+ const [hasFetched, setHasFetched] = useState(false);
+
+ const emailHref = user?.email ? `mailto:${user.email}` : undefined;
+ const resumeHref =
+ user?.resumeUrl || user?.resumeLink || user?.resume?.url || user?.resume;
+
+ const fetchHexathons = async () => {
+ if (loadingHexathons) return;
+
+ setLoadingHexathons(true);
+ setHexathonError(null);
+ setHasFetched(true);
+
+ try {
+ const userId = user?.userId ?? user?.id ?? user?._id;
+
+ const applicationsResp = await axios.get(
+ apiUrl(Service.REGISTRATION, "/applications"),
+ {
+ params: {
+ userId,
+ hexathon: "hexlabs",
+ },
+ }
+ );
+
+ console.log("applicationsResp.data =", applicationsResp.data);
+
+ const applications: any[] = applicationsResp?.data ?? [];
+ const hexathonIds: string[] = applications
+ .map(
+ (app: any) =>
+ app?.hexathon ?? app?.hexathonId ?? app?.hexathonID
+ )
+ .filter(Boolean);
+
+ if (hexathonIds.length === 0) {
+ setHexathons([]);
+ return;
+ }
+ const hexathonsResp = await axios.get(
+ apiUrl(Service.HEXATHONS, "/hexathons")
+ );
+ const allHexathons: any[] = hexathonsResp?.data ?? [];
+
+ const matchedHexathons = allHexathons.filter(
+ (hex: any) =>
+ hexathonIds.includes(hex?.id) || hexathonIds.includes(hex?._id)
+ );
-// TODO: right now, the UserCard only displays the user's name and email. Create a new modal component that
-// pops up when the card is clicked. In this modal, list all the user's information including name, email, phoneNumber,
-// and userId.
+ setHexathons(matchedHexathons);
+ } catch (error) {
+ console.error("Error while fetching hexathons:", error);
+ setHexathonError("Failed to load hexathons for this user.");
+ } finally {
+ setLoadingHexathons(false);
+ }
+ };
-// TODO: Explore if you can display the email as a link to the user's email that will open up the user's
-// email client and start a new email to that user. Also explore if you can provide a link to the user's resume.
+ return (
+
+
+
+
+ {`${user?.name?.first ?? ""} ${user?.name?.last ?? ""}`}
+
+
+
+
+
+ User ID: {user?.userId ?? "Unknown"}
+
+
+
+ Email:{" "}
+ {emailHref ? (
+
+ {user.email}
+
+ ) : (
+ "Not provided"
+ )}
+
+
+
+ Phone:{" "}
+ {user?.phoneNumber ?? "Not provided"}
+
+
+ {resumeHref ? (
+
+ Resume:{" "}
+
+ View Resume
+
+
+ ) : null}
+
+
-// TODO: In our database structure, every user has a userId that is unique to them. This is the primary key of the user
-// and is referenced in their applications to all of our hexathons. Create a button that when clicked, will retrieve all of
-// the hexathons that the user has applied to. You can use the /applications endpoint of the registration service to do this
-// and the /hexathons endpoint of the hexathons service to get a list of all the hexathons.
+ {hexathonError ? (
+
+ {hexathonError}
+
+ ) : null}
+
+ {loadingHexathons ? (
+
+
+ Fetching applications...
+
+ ) : null}
+
+ {!loadingHexathons && hasFetched && !hexathonError ? (
+ hexathons.length > 0 ? (
+
+ Hexathons:
+ {hexathons.map((hex) => (
+
+ {hex?.name ?? hex?.id ?? hex?._id}
+
+ ))}
+
+ ) : (
+
+ No applications found for this user.
+
+ )
+ ) : null}
+
+
+
+
+
+
+
+ );
+};
const UserCard: React.FC = (props: Props) => {
+ const { isOpen, onOpen, onClose } = useDisclosure();
return (
- {`${props.user.name.first} ${props.user.name.last}`}
+
+ {`${props.user.name.first} ${props.user.name.last}`}
+ = (props: Props) => {
{props.user.email}
+
+
);
};
diff --git a/src/components/UserData.tsx b/src/components/UserData.tsx
index d5aeb78..57da85c 100644
--- a/src/components/UserData.tsx
+++ b/src/components/UserData.tsx
@@ -1,6 +1,6 @@
import React, { useEffect, useState } from "react";
import { apiUrl, Service } from "@hex-labs/core";
-import { SimpleGrid, Text } from "@chakra-ui/react";
+import { Button, SimpleGrid, Text } from "@chakra-ui/react";
import axios from "axios";
import UserCard from "./UserCard";
@@ -26,22 +26,16 @@ const UserData: React.FC = () => {
// finished.
const getUsers = async () => {
-
- // TODO: Use the apiUrl() function to make a request to the /users endpoint of our USERS service. The first argument is the URL
- // of the request, which is created for the hexlabs api through our custom function apiUrl(), which builds the request URL based on
- // the Service enum and the following specific endpoint URL.
-
- // TODO: Also explore some of the other ways to configure the api call such as filtering and pagination.
- // Try to filter all the users with phone numbers starting with 470 or increase the amount of users returned from the default 50 (don't go above 100).
-
- // Postman will be your best friend here, because it's better to test out the API calls in Postman before implementing them here.
-
- // this is the endpoint you want to hit, but don't just hit it directly using axios, use the apiUrl() function to make the request
- const URL = 'https://users.api.hexlabs.org/users/hexlabs';
-
- // uncomment the line below to test if you have successfully made the API call and retrieved the data. The below line takes
- // the raw request response and extracts the actual data that we need from it.
- // setUsers(data?.data?.profiles);
+ const response = await axios.get(apiUrl(Service.USERS, "/users/hexlabs"), {
+ // Request a larger page (default is 50) and ask the API to prefilter.
+ params: { limit: 100, phoneNumberStartsWith: "470", page: 0 },
+ });
+ const profiles: any[] = response?.data ?? [];
+ // Fallback client-side filter so we only show users whose numbers start with 470.
+ const filtered = profiles.filter((profile: any) =>
+ profile?.phoneNumber?.startsWith("470")
+ );
+ setUsers(filtered);
};
document.title = "Hexlabs Users"
getUsers();
@@ -51,15 +45,23 @@ const UserData: React.FC = () => {
// run every time a variable changes, you can put that variable in the array
// and it will run every time that variable changes.
-
- // TODO: Create a function that sorts the users array based on the first name of the users. Then, create a button that
- // calls this function and sorts the users alphabetically by first name. You can use the built in sort() function to do this.
-
+ const sortByFirstName = () => {
+ setUsers(prevUsers =>
+ [...prevUsers].sort((a, b) => {
+ const aName = a?.name?.first || "";
+ const bName = b?.name?.first || "";
+ return aName.localeCompare(bName);
+ })
+ );
+ };
return (
<>
Hexlabs UsersThis is an example of a page that makes an API call to the Hexlabs API to get a list of users.
+