Skip to content

Commit

Permalink
Merge pull request #23 from suiramdev/fix/session-provider
Browse files Browse the repository at this point in the history
Session provider refactoring, including bug fixes and refetch improvements
  • Loading branch information
suiramdev authored Jan 3, 2024
2 parents 57e1893 + 28989cb commit 563bb75
Show file tree
Hide file tree
Showing 9 changed files with 143 additions and 126 deletions.
6 changes: 3 additions & 3 deletions src/components/layout/Topbar.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useSession } from "@/providers/session";
import { useAuth } from "@/providers/auth";
import { useModals } from "@/router";
import { Input } from "@/components/ui/input";
import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar";
Expand All @@ -16,13 +16,13 @@ import { Button } from "@/components/ui/button";
import { LogOutIcon, SettingsIcon } from "lucide-react";

export function Topbar() {
const signOut = useSession((state) => state.signOut);
const { signOut } = useAuth();
const modals = useModals();

return (
<div className="grid grid-cols-3 items-center p-6">
<StoreSwitcher />
<Input type="search" placeholder="Search..." className="max-w-[600px]" onClick={() => modals.open("/search")} />
<Input type="text" placeholder="Search..." className="max-w-[600px]" onClick={() => modals.open("/search")} />
<div className="flex items-center space-x-2 justify-self-end">
<ThemeSwitcher />
<DropdownMenu>
Expand Down
31 changes: 19 additions & 12 deletions src/components/switchers/StoreSwitcher.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
CommandList,
CommandSeparator,
} from "@/components/ui/command";
import { Store } from "@/types";
import { cn } from "@/lib/utils";
import { PlusCircleIcon } from "lucide-react";
import { CreateStoreDialog } from "@/components/dialogs/create-store";
Expand All @@ -30,22 +31,22 @@ const STORES = gql`
`;

export function StoreSwitcher() {
const [opened, open] = useState<boolean>(false);
const { selectedStoreID: selectedStoreId, selectStore } = useSession(
useShallow((state) => ({ selectedStoreID: state.selectedStoreId, selectStore: state.selectStore })),
);
const [open, setOpen] = useState<boolean>(false);
const [openCreateDialog, setOpenCreateDialog] = useState<boolean>(false);
const { data } = useQuery(STORES);

const { selectedStoreId, selectStore } = useSession(
useShallow((state) => ({ selectedStoreId: state.selectedStoreId, selectStore: state.selectStore })),
);

const selectedStore = useMemo(
() => data?.stores.find((store: any) => store.id === selectedStoreId),
[data, selectedStoreId],
);

const [createStoreDialogOpened, openCreateStoreDialog] = useState<boolean>(false);

return (
<>
<Popover open={opened} onOpenChange={open}>
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button variant="outline" role="combobox" className="max-w-[200px]">
{selectedStore && (
Expand All @@ -69,8 +70,14 @@ export function StoreSwitcher() {
<CommandEmpty>No stores found.</CommandEmpty>
<CommandGroup>
{data &&
data.stores.map((store: any) => (
<CommandItem key={store.id} onSelect={() => selectStore(store.id)}>
data.stores.map((store: Store) => (
<CommandItem
key={store.id}
onSelect={() => {
selectStore(store.id);
setOpen(false);
}}
>
<Avatar className="mr-2 h-5 w-5">
<AvatarImage src={`https://avatar.vercel.sh/${store.name}.png`} />
<AvatarFallback>
Expand All @@ -88,8 +95,8 @@ export function StoreSwitcher() {
<CommandGroup>
<CommandItem
onSelect={() => {
openCreateStoreDialog(true);
open(false);
setOpenCreateDialog(true);
setOpen(false);
}}
>
<PlusCircleIcon className="mr-2 h-5 w-5" />
Expand All @@ -100,7 +107,7 @@ export function StoreSwitcher() {
</Command>
</PopoverContent>
</Popover>
<CreateStoreDialog open={createStoreDialogOpened} onOpenChange={openCreateStoreDialog} />
<CreateStoreDialog open={openCreateDialog} onOpenChange={setOpenCreateDialog} />
</>
);
}
22 changes: 10 additions & 12 deletions src/lib/apollo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,25 +25,23 @@ const REFRESH_TOKEN = gql`
`;

const refreshToken = async () => {
const refreshToken = useSession.getState().tokens?.refresh;
const refreshToken = useSession.getState().tokens!.refresh; // In this context, we know that the refresh token is defined

const { errors, data } = await apolloClient.mutate({ mutation: REFRESH_TOKEN, variables: { refreshToken } });
try {
const { data } = await apolloClient.mutate({ mutation: REFRESH_TOKEN, variables: { refreshToken } });

if (errors) {
useSession.setState({
tokens: {
access: data.refreshToken.accessToken,
refresh: data.refreshToken.refreshToken,
},
});
} catch (err) {
useSession.setState({
tokens: undefined,
status: SessionStatus.UNAUTHENTICATED,
});

return;
}

useSession.setState({
tokens: {
access: data.refreshToken.accessToken,
refresh: data.refreshToken.refreshToken,
},
});
};

const errorLink = onError(({ graphQLErrors, forward, operation }) => {
Expand Down
12 changes: 6 additions & 6 deletions src/pages/(dashboard)/settings/access-control/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { z } from "zod";
import { roleModel, userModel } from "@/types";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { useEffect, useState } from "react";
import { useState } from "react";
import { toast } from "sonner";
import { apolloClient } from "@/lib/apollo";
import { Form } from "@/components/ui/form";
Expand Down Expand Up @@ -61,11 +61,11 @@ function AccessControlSettingsPage() {
},
});

const { data } = useQuery(ACCCESS_CONTROL_SETTINGS);

useEffect(() => {
if (data) form.reset(data);
}, [data]);
useQuery(ACCCESS_CONTROL_SETTINGS, {
onCompleted: (data) => {
form.reset(data);
},
});

const [removedRoles, setRemovedRoles] = useState<string[]>([]);
const [deleteRoles] = useMutation(DELETE_ROLES, {
Expand Down
10 changes: 4 additions & 6 deletions src/pages/(dashboard)/settings/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { CurrencyCode } from "@/types";
import { useSession } from "@/providers/session";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { useEffect } from "react";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import { Separator } from "@/components/ui/separator";
Expand Down Expand Up @@ -59,16 +58,15 @@ function SettingsPage() {
},
});

const { data } = useQuery(GENERAL_SETTINGS, {
useQuery(GENERAL_SETTINGS, {
variables: {
storeId: selectedStoreId,
},
onCompleted: (data) => {
form.reset(data);
},
});

useEffect(() => {
if (data) form.reset(data);
}, [data]);

const [updateStore] = useMutation(UPDATE_STORE, {
refetchQueries: ["GeneralSettings"],
onCompleted: () => toast.success("Settings updated"),
Expand Down
7 changes: 4 additions & 3 deletions src/pages/_login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { zodResolver } from "@hookform/resolvers/zod";
import * as z from "zod";
import { useForm } from "react-hook-form";
import { SessionStatus, useSession } from "@/providers/session";
import { useShallow } from "zustand/react/shallow";
import { useAuth } from "@/providers/auth";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
Expand All @@ -22,10 +22,11 @@ function LoginPage() {
},
});

const { status, signIn } = useSession(useShallow((state) => ({ status: state.status, signIn: state.signIn })));
const status = useSession((state) => state.status);
const { signIn } = useAuth();

return (
<div className="grid min-h-screen grid-cols-2">
<div className="grid min-h-screen md:grid-cols-2">
<div className="flex flex-col justify-between gap-16 bg-primary-foreground p-16">
<h1 className="text-4xl font-bold">Welcome to Storedge</h1>
<p className="mt-2 text-xl">
Expand Down
15 changes: 11 additions & 4 deletions src/pages/_store-selection.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { gql, useQuery } from "@apollo/client";
import { useSession } from "@/providers/session";
import { useAuth } from "@/providers/auth";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Store } from "@/types";
import { Button } from "@/components/ui/button";
import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar";
import { Skeleton } from "@/components/ui/skeleton";
import { CreateStoreDialog } from "@/components/dialogs/create-store";
import { PlusCircleIcon } from "lucide-react";
import { LogOutIcon, PlusCircleIcon } from "lucide-react";

const STORES = gql`
query Stores {
Expand All @@ -18,25 +20,26 @@ const STORES = gql`

function StoreSelectionPage() {
const selectStore = useSession((state) => state.selectStore);
const { signOut } = useAuth();
const { data } = useQuery(STORES);

return (
<div className="grid min-h-screen grid-cols-2">
<div className="grid min-h-screen md:grid-cols-2">
<div className="flex flex-col justify-between gap-16 bg-primary-foreground p-16">
<h1 className="text-4xl font-bold">Welcome to Storedge</h1>
<p className="mt-2 text-xl">
Storedge is a headless e-commerce platform with a focus on developer experience and performance.
</p>
</div>
<div className="bg-primary-background flex items-center justify-center p-8">
<div className="bg-primary-background flex flex-col items-center justify-center space-y-6 p-8">
<Card className="w-[400px]">
<CardHeader>
<CardTitle>Select a store</CardTitle>
<CardDescription>Select a store to continue.</CardDescription>
</CardHeader>
<CardContent className="flex flex-col space-y-2">
{data &&
data.stores.map((store: any) => (
data.stores.map((store: Store) => (
<Button
variant="outline"
className="justify-start"
Expand All @@ -60,6 +63,10 @@ function StoreSelectionPage() {
</CreateStoreDialog>
</CardContent>
</Card>
<Button variant="outline" className="w-[400px]" onClick={signOut}>
<LogOutIcon className="mr-2 h-4 w-4" />
Sign out
</Button>
</div>
</div>
);
Expand Down
64 changes: 64 additions & 0 deletions src/providers/auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { apolloClient } from "@/lib/apollo";
import { SessionStatus, useSession } from "./session";
import { gql } from "@apollo/client";

const signIn = async (email: string, password: string): Promise<void> => {
try {
useSession.setState((state) => ({
...state,
status: SessionStatus.LOADING,
}));

const { data } = await apolloClient.mutate({
mutation: gql`
mutation SignIn($email: String!, $password: String!) {
generateToken(email: $email, password: $password) {
accessToken
refreshToken
}
}
`,
variables: { email, password },
});

useSession.setState((state) => ({
...state,
status: SessionStatus.AUTHENTICATED,
tokens: {
access: data.generateToken.accessToken,
refresh: data.generateToken.refreshToken,
},
}));

apolloClient.resetStore();
} catch (error) {
useSession.setState((state) => ({
...state,
status: SessionStatus.UNAUTHENTICATED,
tokens: undefined,
}));
}
};

const signOut = async (): Promise<void> => {
await apolloClient.mutate({
mutation: gql`
mutation SignOut {
revokeToken
}
`,
});

useSession.setState((state) => ({
...state,
status: SessionStatus.UNAUTHENTICATED,
tokens: undefined,
}));

apolloClient.resetStore();
};

export const useAuth = () => ({
signIn,
signOut,
});
Loading

0 comments on commit 563bb75

Please sign in to comment.