8000 Added magento-send-friend package by paales · Pull Request #2484 · graphcommerce-org/graphcommerce · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Added magento-send-friend package #2484

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: canary
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,274 @@
import {
ApolloErrorSnackbar,
EmailElement,
FormPersist,
TextFieldElement,
useFieldArray,
useFormGqlMutation,
type Control,
} from '@graphcommerce/ecommerce-ui'
import { useQuery } from '@graphcommerce/graphql'
import {
CustomerDocument,
useCustomerQuery,
useCustomerSession,
} from '@graphcommerce/magento-customer'
import type { ProductPageItemFragment } from '@graphcommerce/magento-product'
import { StoreConfigDocument } from '@graphcommerce/magento-store'
import {
Button,
Container,
extendableComponent,
Fab,
FormRow,
iconClose,
iconEmail,
IconSvg,
LinkOrButton,
Overlay,
OverlayHeader,
sxx,
} from '@graphcommerce/next-ui'
import { alpha, Box, IconButton } from '@mui/material'
import { useState } from 'react'
import {
SendEmailToFriendDocument,
type SendEmailToFriendMutationVariables,
} from '../../graphql/SendEmailToFriend.gql'

export type SendEmailToFriendProps = {
product: ProductPageItemFragment
}

const componentName = 'SendEmailToFriend'
const { classes } = extendableComponent(componentName, ['root', 'recipients', 'recipient'])

function FieldArray(props: { control: Control<SendEmailToFriendMutationVariables> }) {
const { control } = props
const recipients = useFieldArray({
control,
name: 'input.recipients',
rules: { minLength: 1 },
})

return (
<>
<Box
component='h5'
sx={(theme) => ({
typography: 'h6',
display: 'flex',
justifyContent: 'space-between',
alignItems: 'end',
gap: theme.spacings.xs,
mb: theme.spacings.xs,
})}
>
<Box>Recipients</Box>
<Button
=> recipients.append({ name: '', email: '' })}
variant='pill'
color='inherit'
>
Add recipient
</Button>
</Box>
<Box sx={{ display: 'flex', flexDirection: 'column' }} className={classes.recipients}>
{recipients.fields.map((recipient, idx) => (
<Box
className={classes.recipient}
key={recipient.id}
sx={(theme) => ({
display: 'grid',
gridTemplateColumns: '1fr 1fr auto',
gap: theme.spacings.xs,
p: theme.spacings.xs,
border: `1px solid ${theme.palette.divider}`,
borderRadius: theme.shape.borderRadius,

'&:not(:first-child)': {
borderTopLeftRadius: 0,
borderTopRightRadius: 0,
borderTop: 'none',
},
'&:not(:last-child)': {
borderBottomLeftRadius: 0,
borderBottomRightRadius: 0,
},
})}
>
<TextFieldElement
control={control}
name={`input.recipients.${idx}.name`}
label='Name'
required
/>
<EmailElement
control={control}
name={`input.recipients.${idx}.email`}
label='Email'
required
/>
<Box>
<IconButton
=> recipients.remove(idx)}
size='small'
disabled={recipients.fields.length === 1}
>
<IconSvg src={iconClose} />
</IconButton>
</Box>
</Box>
))}
</Box>
</>
)
}

export function SendEmailToFriendForm(props: SendEmailToFriendProps & { onClose: () => void }) {
const { product, onClose } = props

const customer = useCustomerQuery(CustomerDocument).data?.customer
const name = customer
? [customer.prefix, customer.firstname, customer.middlename, customer.lastname, customer.suffix]
.filter((v) => !!v)
.join(' ')
: undefined
const email = customer?.email ?? undefined

const form = useFormGqlMutation(
SendEmailToFriendDocument,
{
defaultValues: {
input: {
sender: { name, email },
product_id: product.id ?? undefined,
recipients: [{}],
},
},
onComplete: () => {},
},
{ errorPolicy: 'all' },
)
const submit = form.handleSubmit(() => {})

return (
<form noValidate>
<OverlayHeader
>
primary={
<LinkOrButton
type='submit'
button={{ variant: 'pill' }}
color='primary'
loading={form.formState.isSubmitting}
>
Send
</LinkOrButton>
}
>
Send to friend
</OverlayHeader>

<Container maxWidth='md' sx={(theme) => ({ pt: theme.spacings.md })}>
<FormRow>
<TextFieldElement
control={form.control}
name='input.sender.name'
label='From Name'
required
variant='outlined'
/>
<EmailElement
control={form.control}
name='input.sender.email'
label='From Email'
required
/>
</FormRow>
<FormRow>
<TextFieldElement
multiline
minRows={4}
control={form.control}
name='input.sender.message'
label='Message'
required
/>
</FormRow>

<FieldArray control={form.control} />

<ApolloErrorSnackbar error={form.error} />
</Container>

<FormPersist form={form} name='SendEmailToFriend' />
</form>
)
}

export function SendEmailToFriendBase(props: SendEmailToFriendProps) {
const { product } = props

const [open, setOpen] = useState(true)

const preventAnimationBubble = (
e: React.TouchEvent<HTMLButtonElement> | React.MouseEvent<HTMLButtonElement>,
) => {
e.stopPropagation()
if (e.type === 'mousedown') {
e.preventDefault()
}
}

return (
<>
<Fab
=> {
e.preventDefault()
setOpen(true)
}}
>
>
size='responsive'
color='inherit'
sx={sxx((theme) => ({
boxShadow: theme.shadows[6],
backgroundColor:
theme.palette.mode === 'light' ? theme.palette.background.paper : 'transparent',
flex: '0 0 auto',
'& svg': {
stroke:
theme.palette.mode === 'light'
? theme.palette.text.secondary
: theme.palette.background.paper,
},
'&:hover': {
backgroundColor: alpha(theme.palette.text.primary, theme.palette.action.hoverOpacity),
},
}))}
title='Send to friend'
aria-label='Send to friend'
icon={iconEmail}
loading={false}
/>

<Overlay active={open} => setOpen(false)}>
<SendEmailToFriendForm product={product} => setOpen(false)} />
</Overlay>
</>
)
}

export function SendEmailToFriend(props: SendEmailToFriendProps) {
const { product } = props

const { enabled_for_customers = false, enabled_for_guests = false } =
useQuery(StoreConfigDocument).data?.storeConfig?.send_friend ?? {}

const { loggedIn } = useCustomerSession()
if (loggedIn && !enabled_for_customers) return null
if (!loggedIn && !enabled_for_guests) return null

return <SendEmailToFriendBase product={product} />
}
13 changes: 13 additions & 0 deletions packages/magento-send-friend/graphql/SendEmailToFriend.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
mutation SendEmailToFriend($input: SendEmailToFriendInput!) {
sendEmailToFriend(input: $input) {
recipients {
email
name
}
sender {
email
name
message
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
fragment SendFriendStoreConfig on StoreConfig @inject(into: ["StoreConfigFragment"]) {
send_friend {
enabled_for_customers
enabled_for_guests
}
}
34 changes: 34 additions & 0 deletions packages/magento-send-friend/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"name": "@graphcommerce/magento-send-friend",
"homepage": "https://www.graphcommerce.org/",
"repository": "github:graphcommerce-org/graphcommerce",
"version": "9.0.4-canary.9",
"sideEffects": false,
"prettier": "@graphcommerce/prettier-config-pwa",
"eslintConfig": {
"extends": "@graphcommerce/eslint-config-pwa",
"parserOptions": {
"project": "./tsconfig.json"
}
},
"peerDependencies": {
"@graphcommerce/ecommerce-ui": "^9.0.4-canary.9",
"@graphcommerce/eslint-config-pwa": "^9.0.4-canary.9",
"@graphcommerce/framer-utils": "^9.0.4-canary.9",
"@graphcommerce/graphql": "^9.0.4-canary.9",
"@graphcommerce/magento-customer": "^9.0.4-canary.9",
"@graphcommerce/magento-product": "^9.0.4-canary.9",
"@graphcommerce/magento-store": "^9.0.4-canary.9",
"@graphcommerce/next-ui": "^9.0.4-canary.9",
"@graphcommerce/prettier-config-pwa": "^9.0.4-canary.9",
"@graphcommerce/typescript-config-pwa": "^9.0.4-canary.9",
"@lingui/core": "^4.2.1",
"@lingui/macro": "^4.2.1",
"@lingui/react": "^4.2.1",
"@mui/material": "^5.10.16",
"framer-motion": "*",
"next": "*",
"react": "^18.2.0",
"react-dom": "^18.2.0"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { ProductPageAddToCartRowProps } from '@graphcommerce/magento-product'
import type { PluginConfig, PluginProps } from '@graphcommerce/next-config'
import { SendEmailToFriend } from '../components/SendEmailToFriend/SendEmailToFriend'

export const config: PluginConfig = {
type: 'component',
module: '@graphcommerce/magento-product',
}

export function ProductPageAddToCartActionsRow(props: PluginProps<ProductPageAddToCartRowProps>) {
const { Prev, product, children, ...rest } = props

return (
<Prev product={product} {...rest}>
{children}
<SendEmailToFriend product={product} />
</Prev>
)
}
3 changes: 3 additions & 0 deletions packages/next-ui/icons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ export { default as iconBin } from './icons/bin.svg'
export { default as iconInvoice } from './icons/box-alt.svg'
export { default as iconBox } from './icons/box.svg'
export { default as iconOrderBefore } from './icons/calendar.svg'
export { default as iconShare } from './icons/share.svg'
export { default as iconShareIos } from './icons/share-ios.svg'
export { default as iconShareAndroid } from './icons/share-android.svg'
export { default as iconCancelAlt } from './icons/cancel-alt.svg'
export { default as iconCancel } from './icons/cancel.svg'
export { default as iconCartAdd } from './icons/cart-add.svg'
Expand Down
Loading
0