Skip to content

Commit

Permalink
Merge pull request #86 from masagal/dev
Browse files Browse the repository at this point in the history
add user page
  • Loading branch information
sighmoan authored Aug 1, 2024
2 parents 873dcf7 + 4199e35 commit a3e4a6b
Show file tree
Hide file tree
Showing 17 changed files with 564 additions and 164 deletions.
36 changes: 36 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"axios": "^1.7.2",
"framer-motion": "^11.3.17",
"react": "^18.2.0",
"react-copy-to-clipboard": "^5.1.0",
"react-dom": "^18.2.0",
"react-icons": "^5.2.1",
"react-markdown": "^9.0.1",
Expand All @@ -35,6 +36,7 @@
"@tanstack/eslint-plugin-query": "^5.51.12",
"@types/jest": "^29.5.12",
"@types/react": "^18.2.66",
"@types/react-copy-to-clipboard": "^5.0.7",
"@types/react-dom": "^18.2.22",
"@typescript-eslint/eslint-plugin": "^7.2.0",
"@typescript-eslint/parser": "^7.2.0",
Expand Down
116 changes: 108 additions & 8 deletions src/ApiQueries/useUserData.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { useAuth } from "@clerk/clerk-react";
import { useQuery } from "@tanstack/react-query";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { useNavigate } from "@tanstack/react-router";
import { GetToken } from "@clerk/types";
import { UserData } from "../utils/types";
import { UserData, NewUserData } from "../utils/types";

const apiHost = import.meta.env.VITE_API_HOST;
const usersEndpoint = "/api/users";
const meEndpoint = "/api/users/me";

const getUserData = async (
Expand All @@ -16,14 +17,72 @@ const getUserData = async (
headers.append("Authorization", `Bearer ${token}`);
return fetch(`${apiHost}${meEndpoint}`, {
headers,
}).then((response) => {
console.log(response);
if (response.ok) return response.json();
navigate({ to: "/error/user-not-found" });
})
.then((response) => {
console.log("get my user data responds:");
console.log(response);
if (response.ok) return response.json();
navigate({ to: "/error/user-not-found" });
})
.catch(() => Promise.reject());
};

const getAllUsers = async (getToken: GetToken): Promise<UserData[]> => {
const token = await getToken();

const url = `${apiHost}${usersEndpoint}`;
const headers = new Headers();
headers.append("Authorization", `Bearer ${token}`);
return fetch(url, { headers })
.then((response) => {
if (!response.ok) {
throw new Error("failed to fetch user data");
}
return response.json();
})
.then((data) => {
console.log(data);
return data;
});
};

const createUser = async (
getToken: GetToken,
newUser: NewUserData
): Promise<UserData> => {
const token = await getToken();

const url = `${apiHost}${usersEndpoint}`;
const headers = new Headers();
headers.append("Content-Type", "application/json");
headers.append("Authorization", `Bearer ${token}`);

return fetch(url, {
method: "POST",
body: JSON.stringify(newUser),
headers,
})
.then((response) => {
if (!response.ok) {
throw new Error("failed to create new user");
}
return response.json();
})
.then((data) => {
console.log(data);
return data;
});
};

const useUsers = () => {
const { getToken } = useAuth();
return useQuery({
queryKey: ["users"],
queryFn: () => getAllUsers(getToken),
});
};

const useUserData = () => {
const useMyUserData = () => {
const navigate = useNavigate();
const { getToken } = useAuth();
return useQuery({
Expand All @@ -32,4 +91,45 @@ const useUserData = () => {
});
};

export { useUserData, getUserData };
const useMutateUsers = () => {
const { getToken } = useAuth();
const queryClient = useQueryClient();

return useMutation({
mutationFn: (data: NewUserData) => createUser(getToken, data),
onSettled: () => queryClient.invalidateQueries({ queryKey: ["users"] }),
});
};

const resolveInvitation = async (getToken: GetToken, inviteToken: string) => {
const token = await getToken();

const url = `${apiHost}${usersEndpoint}/resolve-invitation?token=${inviteToken}`;
const headers = new Headers();
headers.append("Authorization", `Bearer ${token}`);
return fetch(url, { headers }).then((response) => {
if (!response.ok) {
throw new Error("could not resolve invite.");
}
Promise.resolve();
});
};

const useInvitation = () => {
const { getToken } = useAuth();

return useMutation({
mutationFn: (inviteToken: string) =>
resolveInvitation(getToken, inviteToken),
});
};

export {
useMyUserData as useUserData,
getUserData,
useUsers,
getAllUsers,
useMutateUsers,
createUser,
useInvitation,
};
2 changes: 1 addition & 1 deletion src/Components/InventoryCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import GrainIcon from "@mui/icons-material/Grain";

export const InventoryCard = ({ product }: { product: Product }) => {
return (
<Card className="inventoryCard" sx={{ width: 300 }}>
<Card className="w-96">
<CardMedia
sx={{ height: 140 }}
image={product.imageUrl ?? "src/assets/placeholder.png"}
Expand Down
5 changes: 3 additions & 2 deletions src/Components/NavContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
} from "@mui/material";
import HomeIcon from "@mui/icons-material/Home";
import InventoryIcon from "@mui/icons-material/Inventory";
import InfoIcon from "@mui/icons-material/Info";
import PeopleAltIcon from '@mui/icons-material/PeopleAlt';
import LocalShippingIcon from "@mui/icons-material/LocalShipping";
import NoteAddIcon from "@mui/icons-material/NoteAdd";
import { ChatGptIcon } from "../IconComponents/ChatGptIcon";
Expand All @@ -21,6 +21,7 @@ const signedInLinks = [
{ text: "My Requests", link: "/requests", showToNonAdmins: true },
{ text: "Inventory", link: "/inventory", showToNonAdmins: false },
{ text: "Order Status", link: "/order-status", showToNonAdmins: false },
{ text: "Users", link: "/users", showToNonAdmins: false }
];

export const NavContent = () => {
Expand Down Expand Up @@ -55,7 +56,7 @@ export const NavContent = () => {
{index === 2 && <NoteAddIcon />}
{index === 3 && <InventoryIcon />}
{index === 4 && <LocalShippingIcon />}
{index === 5 && <InfoIcon />}
{index === 5 && <PeopleAltIcon/>}
</ListItemIcon>
<ListItemText primary={value.text} />
</ListItemButton>
Expand Down
25 changes: 14 additions & 11 deletions src/Components/RequestsForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { toastSuccess, toastError } from "./toastUtils";
import { useQueryClient } from "@tanstack/react-query";
import { MutationProduct } from "../utils/types";
import { SingleProduct } from "../utils/types";
import { Typography, Button } from "@mui/material";

const RequestsForm = () => {
const queryClient = useQueryClient();
Expand Down Expand Up @@ -53,7 +54,7 @@ const RequestsForm = () => {
}

return (
<div className="container mx-auto p-4 mt-8">
<div className="container mx-auto mt-8">
<div className="mb-4">
{requestsInProgress.length > 0 &&
requestsInProgress.map((req) => (
Expand All @@ -73,9 +74,9 @@ const RequestsForm = () => {
>
<div className="flex mb-4 space-x-4">
<div className="w-1/2">
<label className="block mb-2 font-bold" htmlFor="product">
<Typography variant="body1" className="block mb-2 font-bold">
Product
</label>
</Typography>
<form.Field
name="product"
children={(field) => (
Expand Down Expand Up @@ -103,10 +104,10 @@ const RequestsForm = () => {
)}
/>
</div>
<div className="w-1/2">
<label className="block mb-2 font-bold" htmlFor="productQuantity">
<div className="w-fit">
<Typography variant="body1" className="block mb-2 font-bold">
Quantity
</label>
</Typography>
<form.Field
name="productQuantity"
children={(field) => (
Expand All @@ -118,18 +119,20 @@ const RequestsForm = () => {
field.handleChange(Number(e.target.value))
}
type="text"
className="w-full p-2 border rounded"
className="p-2 border rounded"
/>
)}
/>
</div>
</div>
<button
<Button
variant="contained"
color="primary"
type="submit"
className="w-full bg-blue-500 text-white py-2 rounded hover:bg-blue-700"
className="w-full py-2 rounded"
>
Submit Request
</button>
<Typography variant="body1">Submit Request </Typography>
</Button>
</form>
</div>
</div>
Expand Down
4 changes: 4 additions & 0 deletions src/Components/SignedInMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Drawer, Box } from "@mui/material";
import { Account } from "./Account";
import { NavContent } from "./NavContent";
import { useUserData } from "../ApiQueries/useUserData";

export const SignedInMenu = ({
open,
Expand All @@ -9,6 +10,9 @@ export const SignedInMenu = ({
open: boolean;
setOpen: (val: boolean) => void;
}) => {
const { isPending, error } = useUserData();
if (isPending || error) return <></>;

return (
<>
<Account />
Expand Down
Loading

0 comments on commit a3e4a6b

Please sign in to comment.