Skip to content

Commit

Permalink
feat(core): add customer addresses query (#743)
Browse files Browse the repository at this point in the history
  • Loading branch information
bc-alexsaiannyi committed Apr 16, 2024
1 parent 3f19124 commit 5c43cdc
Show file tree
Hide file tree
Showing 8 changed files with 281 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .changeset/tender-flowers-smile.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@bigcommerce/catalyst-core": patch
---

Add customer addresses query
6 changes: 6 additions & 0 deletions .changeset/thin-pumpkins-search.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@bigcommerce/components": minor
"@bigcommerce/docs": minor
---

Add dialog component
73 changes: 73 additions & 0 deletions apps/core/client/queries/get-customer-addresses.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { removeEdgesAndNodes } from '@bigcommerce/catalyst-client';
import { cache } from 'react';

import { getSessionCustomerId } from '~/auth';

import { client } from '..';
import { graphql } from '../graphql';

const GET_CUSTOMER_ADDRESSES_QUERY = graphql(`
query getCustomerAddresses($after: String, $before: String, $first: Int, $last: Int) {
customer {
entityId
addresses(before: $before, after: $after, first: $first, last: $last) {
pageInfo {
hasNextPage
hasPreviousPage
startCursor
endCursor
}
collectionInfo {
totalItems
}
edges {
node {
entityId
firstName
lastName
address1
address2
city
stateOrProvince
countryCode
phone
postalCode
company
}
}
}
}
}
`);

export interface CustomerAddressesArgs {
after?: string;
before?: string;
limit?: number;
}

export const getCustomerAddresses = cache(
async ({ before = '', after = '', limit = 9 }: CustomerAddressesArgs) => {
const customerId = await getSessionCustomerId();
const paginationArgs = before ? { last: limit, before } : { first: limit, after };

const response = await client.fetch({
document: GET_CUSTOMER_ADDRESSES_QUERY,
variables: { ...paginationArgs },
customerId,
fetchOptions: { cache: 'no-store' },
});

const addresses = response.data.customer?.addresses;

if (!addresses) {
return undefined;
}

return {
pageInfo: addresses.pageInfo,
addressesCount: addresses.collectionInfo?.totalItems ?? 0,
addresses: removeEdgesAndNodes({ edges: addresses.edges }),
};
},
);
58 changes: 58 additions & 0 deletions apps/docs/stories/dialog.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { Button } from '@bigcommerce/components/button';
import {
Dialog,
DialogAction,
DialogCancel,
DialogContent,
DialogOverlay,
DialogPortal,
DialogTitle,
DialogTrigger,
} from '@bigcommerce/components/dialog';
import type { Meta, StoryObj } from '@storybook/react';
import { X } from 'lucide-react';

const meta: Meta<typeof Dialog> = {
component: Dialog,
tags: ['autodocs'],
};

export default meta;

type Story = StoryObj<typeof Dialog>;

export const BasicExample: Story = {
args: {
children: <Button className="w-fit">Delete Item</Button>,
},
render: ({ children }) => (
<Dialog>
<DialogTrigger asChild>{children}</DialogTrigger>
<DialogPortal>
<DialogOverlay />
<DialogContent>
<div className="flex gap-4 p-6">
<DialogTitle>Are you sure you want to continue?</DialogTitle>
<DialogCancel asChild>
<Button className="ms-auto w-min p-2" type="button" variant="subtle">
<X />
</Button>
</DialogCancel>
</div>
<div className="flex flex-col gap-2 p-6 lg:flex-row">
<DialogAction asChild>
<Button className="w-full lg:w-fit" variant="primary">
Yes
</Button>
</DialogAction>
<DialogCancel asChild>
<Button className="w-full lg:w-fit" variant="subtle">
Cancel
</Button>
</DialogCancel>
</div>
</DialogContent>
</DialogPortal>
</Dialog>
),
};
2 changes: 1 addition & 1 deletion packages/components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
},
"dependencies": {
"@radix-ui/react-accordion": "^1.1.2",
"@radix-ui/react-alert-dialog": "^1.0.5",
"@radix-ui/react-checkbox": "^1.0.4",
"@radix-ui/react-dialog": "^1.0.5",
"@radix-ui/react-form": "^0.0.3",
"@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-navigation-menu": "^1.1.4",
Expand Down
107 changes: 107 additions & 0 deletions packages/components/src/components/dialog/dialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import * as DialogPrimitive from '@radix-ui/react-alert-dialog';
import { ComponentPropsWithoutRef, ElementRef, forwardRef } from 'react';

import { cn } from '~/lib/utils';

const Dialog = DialogPrimitive.Root;

const DialogTrigger = forwardRef<
ElementRef<typeof DialogPrimitive.Trigger>,
ComponentPropsWithoutRef<typeof DialogPrimitive.Trigger>
>(({ className, ...props }, ref) => (
<DialogPrimitive.Trigger className={cn(className)} ref={ref} {...props} />
));

DialogTrigger.displayName = DialogPrimitive.Trigger.displayName;

const DialogPortal = forwardRef<
ElementRef<'div'>,
ComponentPropsWithoutRef<typeof DialogPrimitive.Portal>
>(({ ...props }, ref) => (
<div ref={ref}>
<DialogPrimitive.Portal {...props} />
</div>
));

DialogPortal.displayName = DialogPrimitive.Portal.displayName;

const DialogOverlay = forwardRef<
ElementRef<typeof DialogPrimitive.Overlay>,
ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
>(({ className, ...props }, ref) => (
<DialogPrimitive.Overlay
className={cn('data-[state=open]:animate-overlayShow fixed inset-0 bg-black/[.2]', className)}
ref={ref}
{...props}
/>
));

DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;

const DialogContent = forwardRef<
ElementRef<typeof DialogPrimitive.Content>,
ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
>(({ className, ...props }, ref) => (
<DialogPrimitive.Content
className={cn(
'data-[state=open]:animate-contentShow fixed left-[50%] top-[50%] w-full translate-x-[-50%] translate-y-[-50%] bg-white shadow-[hsl(206_22%_7%_/_35%)_0px_10px_38px_-10px,_hsl(206_22%_7%_/_20%)_0px_10px_20px_-15px] focus:outline-none md:w-3/4 lg:w-3/5',
className,
)}
ref={ref}
{...props}
/>
));

DialogContent.displayName = DialogPrimitive.Content.displayName;

const DialogTitle = forwardRef<
ElementRef<typeof DialogPrimitive.Title>,
ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
>(({ className, ...props }, ref) => (
<DialogPrimitive.Title
className={cn('w-5/6 grow font-semibold', className)}
ref={ref}
{...props}
/>
));

DialogTitle.displayName = DialogPrimitive.Title.displayName;

const DialogDescription = forwardRef<
ElementRef<typeof DialogPrimitive.Description>,
ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
>(({ className, ...props }, ref) => (
<DialogPrimitive.Description className={cn(className)} ref={ref} {...props} />
));

DialogDescription.displayName = DialogPrimitive.Description.displayName;

const DialogCancel = forwardRef<
ElementRef<typeof DialogPrimitive.Cancel>,
ComponentPropsWithoutRef<typeof DialogPrimitive.Cancel>
>(({ className, ...props }, ref) => (
<DialogPrimitive.Cancel className={cn(className)} ref={ref} {...props} />
));

DialogCancel.displayName = DialogPrimitive.Cancel.displayName;

const DialogAction = forwardRef<
ElementRef<typeof DialogPrimitive.Action>,
ComponentPropsWithoutRef<typeof DialogPrimitive.Action>
>(({ className, ...props }, ref) => (
<DialogPrimitive.Action className={cn(className)} ref={ref} {...props} />
));

DialogAction.displayName = DialogPrimitive.Action.displayName;

export {
Dialog,
DialogTrigger,
DialogPortal,
DialogOverlay,
DialogContent,
DialogTitle,
DialogDescription,
DialogCancel,
DialogAction,
};
3 changes: 3 additions & 0 deletions packages/components/src/components/dialog/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
'use client';

export * from './dialog';
30 changes: 28 additions & 2 deletions pnpm-lock.yaml

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

0 comments on commit 5c43cdc

Please sign in to comment.