can add own/wanted items from item page

the buttons work now! but only when adding 😅 remove comes next!
This commit is contained in:
Emi Matchu 2020-10-22 21:20:49 -07:00
parent d2671d0fa6
commit 57889a3a88
3 changed files with 167 additions and 76 deletions

View file

@ -25,7 +25,7 @@ GRANT INSERT, UPDATE ON swf_assets TO impress2020;
GRANT INSERT ON modeling_logs TO impress2020; GRANT INSERT ON modeling_logs TO impress2020;
-- User data tables -- User data tables
GRANT SELECT ON closet_hangers TO impress2020; GRANT SELECT, INSERT ON closet_hangers TO impress2020;
GRANT SELECT ON closet_lists TO impress2020; GRANT SELECT ON closet_lists TO impress2020;
GRANT SELECT ON item_outfit_relationships TO impress2020; GRANT SELECT ON item_outfit_relationships TO impress2020;
GRANT SELECT ON outfits TO impress2020; GRANT SELECT ON outfits TO impress2020;

View file

@ -25,7 +25,7 @@ import {
} from "@chakra-ui/icons"; } from "@chakra-ui/icons";
import { MdPause, MdPlayArrow } from "react-icons/md"; import { MdPause, MdPlayArrow } from "react-icons/md";
import gql from "graphql-tag"; import gql from "graphql-tag";
import { useQuery } from "@apollo/client"; import { useQuery, useMutation } from "@apollo/client";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import { import {
@ -41,6 +41,7 @@ import {
} from "./components/useOutfitAppearance"; } from "./components/useOutfitAppearance";
import OutfitPreview from "./components/OutfitPreview"; import OutfitPreview from "./components/OutfitPreview";
import SpeciesColorPicker from "./components/SpeciesColorPicker"; import SpeciesColorPicker from "./components/SpeciesColorPicker";
import useCurrentUser from "./components/useCurrentUser";
import { useLocalStorage } from "./util"; import { useLocalStorage } from "./util";
import WIPCallout from "./components/WIPCallout"; import WIPCallout from "./components/WIPCallout";
@ -55,10 +56,12 @@ function ItemPage() {
* `isEmbedded` prop is true, so we know not to e.g. set the page title. * `isEmbedded` prop is true, so we know not to e.g. set the page title.
*/ */
export function ItemPageContent({ itemId, isEmbedded }) { export function ItemPageContent({ itemId, isEmbedded }) {
const { isLoggedIn } = useCurrentUser();
return ( return (
<VStack spacing="8"> <VStack spacing="8">
<ItemPageHeader itemId={itemId} isEmbedded={isEmbedded} /> <ItemPageHeader itemId={itemId} isEmbedded={isEmbedded} />
<ItemPageOwnWantButtons itemId={itemId} /> {isLoggedIn && <ItemPageOwnWantButtons itemId={itemId} />}
{!isEmbedded && <ItemPageOutfitPreview itemId={itemId} />} {!isEmbedded && <ItemPageOutfitPreview itemId={itemId} />}
<WIPCallout>Trade lists coming soon!</WIPCallout> <WIPCallout>Trade lists coming soon!</WIPCallout>
</VStack> </VStack>
@ -311,10 +314,9 @@ function ItemPageOwnWantButtons({ itemId }) {
const theme = useTheme(); const theme = useTheme();
const toast = useToast(); const toast = useToast();
const [currentUserOwnsThis, setCurrentUserOwnsThis] = React.useState(false);
const [currentUserWantsThis, setCurrentUserWantsThis] = React.useState(false); const [currentUserWantsThis, setCurrentUserWantsThis] = React.useState(false);
const { loading, error } = useQuery( const { loading, error, data } = useQuery(
gql` gql`
query ItemPageOwnWantButtons($itemId: ID!) { query ItemPageOwnWantButtons($itemId: ID!) {
item(id: $itemId) { item(id: $itemId) {
@ -327,7 +329,6 @@ function ItemPageOwnWantButtons({ itemId }) {
{ {
variables: { itemId }, variables: { itemId },
onCompleted: (data) => { onCompleted: (data) => {
setCurrentUserOwnsThis(data?.item?.currentUserOwnsThis || false);
setCurrentUserWantsThis(data?.item?.currentUserWantsThis || false); setCurrentUserWantsThis(data?.item?.currentUserWantsThis || false);
}, },
} }
@ -340,82 +341,172 @@ function ItemPageOwnWantButtons({ itemId }) {
return ( return (
<Box display="flex"> <Box display="flex">
<SubtleSkeleton isLoaded={!loading} marginRight="4"> <SubtleSkeleton isLoaded={!loading} marginRight="4">
<Box as="label"> <ItemPageOwnButton
<VisuallyHidden itemId={itemId}
as="input" isChecked={data?.item?.currentUserOwnsThis}
type="checkbox" />
checked={currentUserOwnsThis}
onChange={(e) => {
setCurrentUserOwnsThis(e.target.checked);
toast({
title: "Todo: This doesn't actually work yet!",
status: "info",
duration: 1500,
});
}}
/>
<Button
as="div"
colorScheme={currentUserOwnsThis ? "green" : "gray"}
size="lg"
cursor="pointer"
transitionDuration="0.4s"
className={css`
input:focus + & {
box-shadow: ${theme.shadows.outline};
}
`}
>
<IconCheckbox
icon={<CheckIcon />}
isChecked={currentUserOwnsThis}
marginRight="0.5em"
/>
I own this
</Button>
</Box>
</SubtleSkeleton> </SubtleSkeleton>
<SubtleSkeleton isLoaded={!loading}> <SubtleSkeleton isLoaded={!loading}>
<Box as="label"> <ItemPageWantButton
<VisuallyHidden itemId={itemId}
as="input" isChecked={data?.item?.currentUserWantsThis}
type="checkbox" />
isChecked={currentUserWantsThis}
onChange={(e) => {
setCurrentUserWantsThis(e.target.checked);
toast({
title: "Todo: This doesn't actually work yet!",
status: "info",
duration: 1500,
});
}}
/>
<Button
as="div"
colorScheme={currentUserWantsThis ? "blue" : "gray"}
size="lg"
cursor="pointer"
transitionDuration="0.4s"
className={css`
input:focus + & {
box-shadow: ${theme.shadows.outline};
}
`}
>
<IconCheckbox
icon={<StarIcon />}
isChecked={currentUserWantsThis}
marginRight="0.5em"
/>
I want this
</Button>
</Box>
</SubtleSkeleton> </SubtleSkeleton>
</Box> </Box>
); );
} }
function ItemPageOwnButton({ itemId, isChecked }) {
const theme = useTheme();
const toast = useToast();
const [sendAddMutation] = useMutation(
gql`
mutation ItemPageOwnButtonAdd($itemId: ID!) {
addToItemsCurrentUserOwns(itemId: $itemId) {
id
currentUserOwnsThis
}
}
`,
{
variables: { itemId },
optimisticResponse: {
__typename: "Mutation",
addToItemsCurrentUserOwns: {
__typename: "Item",
id: itemId,
currentUserOwnsThis: true,
},
},
}
);
return (
<Box as="label">
<VisuallyHidden
as="input"
type="checkbox"
checked={isChecked}
onChange={(e) => {
if (e.target.checked) {
sendAddMutation().catch((e) => {
console.error(e);
toast({
title: "We had trouble adding this to the items you own.",
description: "Check your internet connection, and try again.",
status: "error",
duration: 5000,
});
});
} else {
toast({
title: "Todo: This doesn't actually work yet!",
status: "info",
duration: 1500,
});
}
}}
/>
<Button
as="div"
colorScheme={isChecked ? "green" : "gray"}
size="lg"
cursor="pointer"
transitionDuration="0.4s"
className={css`
input:focus + & {
box-shadow: ${theme.shadows.outline};
}
`}
>
<IconCheckbox
icon={<CheckIcon />}
isChecked={isChecked}
marginRight="0.5em"
/>
I own this
</Button>
</Box>
);
}
function ItemPageWantButton({ itemId, isChecked }) {
const theme = useTheme();
const toast = useToast();
const [sendAddMutation] = useMutation(
gql`
mutation ItemPageWantButtonAdd($itemId: ID!) {
addToItemsCurrentUserWants(itemId: $itemId) {
id
currentUserWantsThis
}
}
`,
{
variables: { itemId },
optimisticResponse: {
__typename: "Mutation",
addToItemsCurrentUserWants: {
__typename: "Item",
id: itemId,
currentUserWantsThis: true,
},
},
}
);
return (
<Box as="label">
<VisuallyHidden
as="input"
type="checkbox"
isChecked={isChecked}
onChange={(e) => {
if (e.target.checked) {
sendAddMutation().catch((e) => {
console.error(e);
toast({
title: "We had trouble adding this to the items you want.",
description: "Check your internet connection, and try again.",
status: "error",
duration: 5000,
});
});
} else {
toast({
title: "Todo: This doesn't actually work yet!",
status: "info",
duration: 1500,
});
}
}}
/>
<Button
as="div"
colorScheme={isChecked ? "blue" : "gray"}
size="lg"
cursor="pointer"
transitionDuration="0.4s"
className={css`
input:focus + & {
box-shadow: ${theme.shadows.outline};
}
`}
>
<IconCheckbox
icon={<StarIcon />}
isChecked={isChecked}
marginRight="0.5em"
/>
I want this
</Button>
</Box>
);
}
function IconCheckbox({ icon, isChecked, ...props }) { function IconCheckbox({ icon, isChecked, ...props }) {
return ( return (
<Box display="grid" gridTemplateAreas="the-same-area" {...props}> <Box display="grid" gridTemplateAreas="the-same-area" {...props}>

View file

@ -4,7 +4,7 @@ function useCurrentUser() {
const { isLoading, isAuthenticated, user } = useAuth0(); const { isLoading, isAuthenticated, user } = useAuth0();
if (isLoading || !isAuthenticated) { if (isLoading || !isAuthenticated) {
return { id: null, username: null }; return { id: null, username: null, isLoggedIn: false };
} }
// NOTE: Users created correctly should have these attributes... but I'm // NOTE: Users created correctly should have these attributes... but I'm
@ -13,7 +13,7 @@ function useCurrentUser() {
const id = user.sub?.match(/^auth0\|impress-([0-9]+)$/)?.[1]; const id = user.sub?.match(/^auth0\|impress-([0-9]+)$/)?.[1];
const username = user["https://oauth.impress-2020.openneo.net/username"]; const username = user["https://oauth.impress-2020.openneo.net/username"];
return { id, username }; return { id, username, isLoggedIn: true };
} }
export default useCurrentUser; export default useCurrentUser;