mirror of
https://github.com/vercel/commerce.git
synced 2025-07-22 20:26:49 +00:00
Merge pull request #65 from KieIO/feature/login-signup
Add Login, Signup and Active Customer API Hook
This commit is contained in:
@@ -1,45 +1,62 @@
|
|||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
|
import { useRouter } from 'next/router'
|
||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import useActiveCustomer from 'src/components/hooks/useActiveCustomer'
|
||||||
|
import { ROUTE } from 'src/utils/constanst.utils'
|
||||||
import ModalCommon from '../ModalCommon/ModalCommon'
|
import ModalCommon from '../ModalCommon/ModalCommon'
|
||||||
import FormLogin from './components/FormLogin/FormLogin'
|
import FormLogin from './components/FormLogin/FormLogin'
|
||||||
import FormRegister from './components/FormRegister/FormRegister'
|
import FormRegister from './components/FormRegister/FormRegister'
|
||||||
import s from './ModalAuthenticate.module.scss'
|
import s from './ModalAuthenticate.module.scss'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
visible: boolean,
|
visible: boolean
|
||||||
closeModal: () => void,
|
closeModal: () => void
|
||||||
mode?: '' | 'register'
|
mode?: '' | 'register'
|
||||||
}
|
}
|
||||||
|
|
||||||
const ModalAuthenticate = ({ visible, mode, closeModal }: Props) => {
|
const ModalAuthenticate = ({ visible, mode, closeModal }: Props) => {
|
||||||
const [isLogin, setIsLogin] = useState<boolean>(true)
|
const [isLogin, setIsLogin] = useState<boolean>(true)
|
||||||
|
const { customer } = useActiveCustomer()
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (mode === 'register') {
|
if (mode === 'register') {
|
||||||
setIsLogin(false)
|
setIsLogin(false)
|
||||||
} else {
|
} else {
|
||||||
setIsLogin(true)
|
setIsLogin(true)
|
||||||
}
|
|
||||||
}, [mode])
|
|
||||||
|
|
||||||
const onSwitch = () => {
|
|
||||||
setIsLogin(!isLogin)
|
|
||||||
}
|
}
|
||||||
|
}, [mode])
|
||||||
|
|
||||||
return (
|
useEffect(() => {
|
||||||
<ModalCommon visible={visible} onClose={closeModal} title={isLogin ? 'Sign In' : 'Create Account'}>
|
if (visible && customer) {
|
||||||
<section className={s.formAuthenticate}>
|
closeModal()
|
||||||
<div className={classNames({
|
router.push(ROUTE.ACCOUNT)
|
||||||
[s.inner]: true,
|
}
|
||||||
[s.register]: !isLogin,
|
}, [customer, visible])
|
||||||
})}>
|
|
||||||
<FormLogin isHide={!isLogin} onSwitch={onSwitch} />
|
|
||||||
<FormRegister isHide={isLogin} onSwitch={onSwitch} />
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</ModalCommon>
|
|
||||||
|
|
||||||
)
|
const onSwitch = () => {
|
||||||
|
setIsLogin(!isLogin)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ModalCommon
|
||||||
|
visible={visible}
|
||||||
|
onClose={closeModal}
|
||||||
|
title={isLogin ? 'Sign In' : 'Create Account'}
|
||||||
|
>
|
||||||
|
<section className={s.formAuthenticate}>
|
||||||
|
<div
|
||||||
|
className={classNames({
|
||||||
|
[s.inner]: true,
|
||||||
|
[s.register]: !isLogin,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<FormLogin isHide={!isLogin} onSwitch={onSwitch} />
|
||||||
|
<FormRegister isHide={isLogin} onSwitch={onSwitch} />
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</ModalCommon>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ModalAuthenticate
|
export default ModalAuthenticate
|
||||||
|
@@ -1,51 +1,78 @@
|
|||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import React, { useEffect, useRef } from 'react'
|
import React, { useEffect, useRef, useState } from 'react'
|
||||||
import { ButtonCommon, Inputcommon, InputPassword } from 'src/components/common'
|
import { ButtonCommon, Inputcommon, InputPassword } from 'src/components/common'
|
||||||
import { ROUTE } from 'src/utils/constanst.utils'
|
import { ROUTE } from 'src/utils/constanst.utils'
|
||||||
import { CustomInputCommon } from 'src/utils/type.utils'
|
import { CustomInputCommon } from 'src/utils/type.utils'
|
||||||
|
import useLogin from 'src/components/hooks/useLogin'
|
||||||
import s from '../FormAuthen.module.scss'
|
import s from '../FormAuthen.module.scss'
|
||||||
import SocialAuthen from '../SocialAuthen/SocialAuthen'
|
import SocialAuthen from '../SocialAuthen/SocialAuthen'
|
||||||
import styles from './FormLogin.module.scss'
|
import styles from './FormLogin.module.scss'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
isHide: boolean,
|
isHide: boolean
|
||||||
onSwitch: () => void
|
onSwitch: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const FormLogin = ({ onSwitch, isHide }: Props) => {
|
const FormLogin = ({ onSwitch, isHide }: Props) => {
|
||||||
const emailRef = useRef<CustomInputCommon>(null)
|
const emailRef = useRef<CustomInputCommon>(null)
|
||||||
|
const { loading, login, error } = useLogin()
|
||||||
|
const [email, setEmail] = useState('')
|
||||||
|
const [password, setPassword] = useState('')
|
||||||
|
|
||||||
useEffect(() => {
|
const onLogin = () => {
|
||||||
if (!isHide) {
|
login({ username: email, password })
|
||||||
emailRef.current?.focus()
|
}
|
||||||
}
|
|
||||||
}, [isHide])
|
|
||||||
|
|
||||||
return (
|
useEffect(() => {
|
||||||
<section className={s.formAuthen}>
|
if (!isHide) {
|
||||||
<div className={s.inner}>
|
emailRef.current?.focus()
|
||||||
<div className={s.body}>
|
}
|
||||||
<Inputcommon placeholder='Email Address' type='email' ref={emailRef} />
|
}, [isHide])
|
||||||
{/* <Inputcommon placeholder='Email Address' type='email' ref={emailRef}
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (error) {
|
||||||
|
alert(error.message)
|
||||||
|
}
|
||||||
|
}, [error])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className={s.formAuthen}>
|
||||||
|
<div className={s.inner}>
|
||||||
|
<div className={s.body}>
|
||||||
|
<Inputcommon
|
||||||
|
placeholder="Email Address"
|
||||||
|
value={email}
|
||||||
|
onChange={(val) => setEmail(val.toString())}
|
||||||
|
type="email"
|
||||||
|
ref={emailRef}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* <Inputcommon placeholder='Email Address' type='email' ref={emailRef}
|
||||||
isShowIconSuccess={true} isIconSuffix={true} /> */}
|
isShowIconSuccess={true} isIconSuffix={true} /> */}
|
||||||
<InputPassword placeholder='Password'/>
|
<InputPassword
|
||||||
</div>
|
placeholder="Password"
|
||||||
<div className={styles.bottom}>
|
value={password}
|
||||||
<Link href={ROUTE.FORGOT_PASSWORD}>
|
onChange={(val) => setPassword(val.toString())}
|
||||||
<a href="" className={styles.forgotPassword}>
|
/>
|
||||||
Forgot Password?
|
</div>
|
||||||
</a>
|
<div className={styles.bottom}>
|
||||||
</Link>
|
<Link href={ROUTE.FORGOT_PASSWORD}>
|
||||||
<ButtonCommon size='large'>Sign in</ButtonCommon>
|
<a href="" className={styles.forgotPassword}>
|
||||||
</div>
|
Forgot Password?
|
||||||
<SocialAuthen />
|
</a>
|
||||||
<div className={s.others}>
|
</Link>
|
||||||
<span>Don't have an account?</span>
|
<ButtonCommon onClick={onLogin} loading={loading} size="large">
|
||||||
<button onClick={onSwitch}>Create Account</button>
|
Sign in
|
||||||
</div>
|
</ButtonCommon>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
<SocialAuthen />
|
||||||
)
|
<div className={s.others}>
|
||||||
|
<span>Don't have an account?</span>
|
||||||
|
<button onClick={onSwitch}>Create Account</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default FormLogin
|
export default FormLogin
|
||||||
|
22
src/components/hooks/useActiveCustomer.tsx
Normal file
22
src/components/hooks/useActiveCustomer.tsx
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { ActiveCustomerQuery } from '@framework/schema'
|
||||||
|
import { gql } from 'graphql-request'
|
||||||
|
import gglFetcher from 'src/utils/gglFetcher'
|
||||||
|
import useSWR from 'swr'
|
||||||
|
|
||||||
|
const query = gql`
|
||||||
|
query activeCustomer {
|
||||||
|
activeCustomer {
|
||||||
|
id
|
||||||
|
firstName
|
||||||
|
lastName
|
||||||
|
emailAddress
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const useActiveCustomer = () => {
|
||||||
|
const { data, ...rest } = useSWR<ActiveCustomerQuery>([query], gglFetcher)
|
||||||
|
return { customer: data?.activeCustomer, ...rest }
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useActiveCustomer
|
57
src/components/hooks/useLogin.tsx
Normal file
57
src/components/hooks/useLogin.tsx
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
import { gql } from 'graphql-request'
|
||||||
|
import { useState } from 'react'
|
||||||
|
import useActiveCustomer from './useActiveCustomer'
|
||||||
|
import { CommonError } from 'src/domains/interfaces/CommonError'
|
||||||
|
import rawFetcher from 'src/utils/rawFetcher'
|
||||||
|
import { LoginMutation } from '@framework/schema'
|
||||||
|
|
||||||
|
const query = gql`
|
||||||
|
mutation login($username: String!, $password: String!) {
|
||||||
|
login(username: $username, password: $password) {
|
||||||
|
__typename
|
||||||
|
... on CurrentUser {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
... on ErrorResult {
|
||||||
|
errorCode
|
||||||
|
message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
interface LoginInput {
|
||||||
|
username: string
|
||||||
|
password: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const useLogin = () => {
|
||||||
|
const [loading, setLoading] = useState(false)
|
||||||
|
const [error, setError] = useState<CommonError | null>(null)
|
||||||
|
const { mutate } = useActiveCustomer()
|
||||||
|
|
||||||
|
const login = (options: LoginInput) => {
|
||||||
|
setError(null)
|
||||||
|
setLoading(true)
|
||||||
|
rawFetcher<LoginMutation>({
|
||||||
|
query,
|
||||||
|
variables: options,
|
||||||
|
})
|
||||||
|
.then(({ data, headers }) => {
|
||||||
|
if (data.login.__typename !== 'CurrentUser') {
|
||||||
|
throw CommonError.create(data.login.message, data.login.errorCode)
|
||||||
|
}
|
||||||
|
const authToken = headers.get('vendure-auth-token')
|
||||||
|
if (authToken != null) {
|
||||||
|
localStorage.setItem('token', authToken)
|
||||||
|
return mutate()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(setError)
|
||||||
|
.finally(() => setLoading(false))
|
||||||
|
}
|
||||||
|
|
||||||
|
return { loading, login, error }
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useLogin
|
67
src/components/hooks/useSignup.tsx
Normal file
67
src/components/hooks/useSignup.tsx
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
import { gql } from 'graphql-request'
|
||||||
|
import { useState } from 'react'
|
||||||
|
import useActiveCustomer from './useActiveCustomer'
|
||||||
|
import { SignupMutation } from '@framework/schema'
|
||||||
|
import fetcher from 'src/utils/fetcher'
|
||||||
|
import { CommonError } from 'src/domains/interfaces/CommonError'
|
||||||
|
|
||||||
|
const query = gql`
|
||||||
|
mutation signup($input: RegisterCustomerInput!) {
|
||||||
|
registerCustomerAccount(input: $input) {
|
||||||
|
__typename
|
||||||
|
... on Success {
|
||||||
|
success
|
||||||
|
}
|
||||||
|
... on ErrorResult {
|
||||||
|
errorCode
|
||||||
|
message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
interface SignupInput {
|
||||||
|
email: string
|
||||||
|
firstName: string
|
||||||
|
lastName: string
|
||||||
|
password: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const useSignup = () => {
|
||||||
|
const [loading, setLoading] = useState(false)
|
||||||
|
const [error, setError] = useState<Error | null>(null)
|
||||||
|
const { mutate } = useActiveCustomer()
|
||||||
|
|
||||||
|
const signup = ({ firstName, lastName, email, password }: SignupInput) => {
|
||||||
|
setError(null)
|
||||||
|
setLoading(true)
|
||||||
|
fetcher<SignupMutation>({
|
||||||
|
query,
|
||||||
|
variables: {
|
||||||
|
input: {
|
||||||
|
firstName,
|
||||||
|
lastName,
|
||||||
|
emailAddress: email,
|
||||||
|
password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((data) => {
|
||||||
|
if (data.registerCustomerAccount.__typename !== 'Success') {
|
||||||
|
throw CommonError.create(
|
||||||
|
data.registerCustomerAccount.message,
|
||||||
|
data.registerCustomerAccount.errorCode
|
||||||
|
)
|
||||||
|
}
|
||||||
|
console.log(data)
|
||||||
|
mutate()
|
||||||
|
return data
|
||||||
|
})
|
||||||
|
.catch(setError)
|
||||||
|
.finally(() => setLoading(false))
|
||||||
|
}
|
||||||
|
|
||||||
|
return { loading, signup, error }
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useSignup
|
@@ -1,56 +1,63 @@
|
|||||||
import React from "react"
|
import React from 'react'
|
||||||
import s from './AccountInfomation.module.scss'
|
import s from './AccountInfomation.module.scss'
|
||||||
|
|
||||||
import Image from "next/image"
|
import Image from 'next/image'
|
||||||
import avatar from '../../assets/avatar.png';
|
import avatar from '../../assets/avatar.png'
|
||||||
|
|
||||||
import { ButtonCommon } from 'src/components/common'
|
import { ButtonCommon } from 'src/components/common'
|
||||||
|
import useActiveCustomer from 'src/components/hooks/useActiveCustomer'
|
||||||
|
|
||||||
interface AccountProps {
|
interface AccountProps {
|
||||||
name: string, email: string, address: string, state: string, city: string, postalCode: string, phoneNumber: string
|
name: string
|
||||||
|
email: string
|
||||||
|
address: string
|
||||||
|
state: string
|
||||||
|
city: string
|
||||||
|
postalCode: string
|
||||||
|
phoneNumber: string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface AccountInfomationProps {
|
interface AccountInfomationProps {
|
||||||
account: AccountProps;
|
account: AccountProps
|
||||||
onClick: () => void;
|
onClick: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const AccountInfomation = ({ account, onClick } : AccountInfomationProps) => {
|
const AccountInfomation = ({ account, onClick }: AccountInfomationProps) => {
|
||||||
|
const { customer } = useActiveCustomer()
|
||||||
|
|
||||||
// need to handle call back when edit account information
|
// need to handle call back when edit account information
|
||||||
|
|
||||||
const showEditForm = () => onClick()
|
const showEditForm = () => onClick()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={s.accountInfomation}>
|
<section className={s.accountInfomation}>
|
||||||
<div className={s.avatar}>
|
<div className={s.avatar}>
|
||||||
<Image src={avatar} alt="avatar" />
|
<Image src={avatar} alt="avatar" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={s.accountName}>
|
<div className={s.accountName}>
|
||||||
{account.name}
|
{customer?.firstName} {customer?.lastName}
|
||||||
</div>
|
</div>
|
||||||
<div className={s.accountEmail}>
|
<div className={s.accountEmail}>{customer?.emailAddress}</div>
|
||||||
{account.email}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={s.horizontalSeparator}></div>
|
<div className={s.horizontalSeparator}></div>
|
||||||
|
|
||||||
<div className={s.shippingInfo}>Shipping Infomation</div>
|
<div className={s.shippingInfo}>Shipping Infomation</div>
|
||||||
|
|
||||||
<div className={s.accountAddress}>
|
<div className={s.accountAddress}>
|
||||||
{account.address + `, ${account.state}, ${account.city}, ${account.postalCode}`}
|
{account.address +
|
||||||
</div>
|
`, ${account.state}, ${account.city}, ${account.postalCode}`}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className={s.accountPhoneNumber}>
|
<div className={s.accountPhoneNumber}>{account.phoneNumber}</div>
|
||||||
{account.phoneNumber}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={s.editInfoBtn}>
|
<div className={s.editInfoBtn}>
|
||||||
<ButtonCommon onClick={showEditForm} type="light" size="small">Edit</ButtonCommon>
|
<ButtonCommon onClick={showEditForm} type="light" size="small">
|
||||||
</div>
|
Edit
|
||||||
</section>
|
</ButtonCommon>
|
||||||
)
|
</div>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AccountInfomation
|
export default AccountInfomation
|
||||||
|
30
src/domains/enums/ErrorCode.ts
Normal file
30
src/domains/enums/ErrorCode.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
export enum ErrorCode {
|
||||||
|
UnknownError = 'UNKNOWN_ERROR',
|
||||||
|
NativeAuthStrategyError = 'NATIVE_AUTH_STRATEGY_ERROR',
|
||||||
|
InvalidCredentialsError = 'INVALID_CREDENTIALS_ERROR',
|
||||||
|
OrderStateTransitionError = 'ORDER_STATE_TRANSITION_ERROR',
|
||||||
|
EmailAddressConflictError = 'EMAIL_ADDRESS_CONFLICT_ERROR',
|
||||||
|
OrderLimitError = 'ORDER_LIMIT_ERROR',
|
||||||
|
NegativeQuantityError = 'NEGATIVE_QUANTITY_ERROR',
|
||||||
|
InsufficientStockError = 'INSUFFICIENT_STOCK_ERROR',
|
||||||
|
OrderModificationError = 'ORDER_MODIFICATION_ERROR',
|
||||||
|
IneligibleShippingMethodError = 'INELIGIBLE_SHIPPING_METHOD_ERROR',
|
||||||
|
OrderPaymentStateError = 'ORDER_PAYMENT_STATE_ERROR',
|
||||||
|
IneligiblePaymentMethodError = 'INELIGIBLE_PAYMENT_METHOD_ERROR',
|
||||||
|
PaymentFailedError = 'PAYMENT_FAILED_ERROR',
|
||||||
|
PaymentDeclinedError = 'PAYMENT_DECLINED_ERROR',
|
||||||
|
CouponCodeInvalidError = 'COUPON_CODE_INVALID_ERROR',
|
||||||
|
CouponCodeExpiredError = 'COUPON_CODE_EXPIRED_ERROR',
|
||||||
|
CouponCodeLimitError = 'COUPON_CODE_LIMIT_ERROR',
|
||||||
|
AlreadyLoggedInError = 'ALREADY_LOGGED_IN_ERROR',
|
||||||
|
MissingPasswordError = 'MISSING_PASSWORD_ERROR',
|
||||||
|
PasswordAlreadySetError = 'PASSWORD_ALREADY_SET_ERROR',
|
||||||
|
VerificationTokenInvalidError = 'VERIFICATION_TOKEN_INVALID_ERROR',
|
||||||
|
VerificationTokenExpiredError = 'VERIFICATION_TOKEN_EXPIRED_ERROR',
|
||||||
|
IdentifierChangeTokenInvalidError = 'IDENTIFIER_CHANGE_TOKEN_INVALID_ERROR',
|
||||||
|
IdentifierChangeTokenExpiredError = 'IDENTIFIER_CHANGE_TOKEN_EXPIRED_ERROR',
|
||||||
|
PasswordResetTokenInvalidError = 'PASSWORD_RESET_TOKEN_INVALID_ERROR',
|
||||||
|
PasswordResetTokenExpiredError = 'PASSWORD_RESET_TOKEN_EXPIRED_ERROR',
|
||||||
|
NotVerifiedError = 'NOT_VERIFIED_ERROR',
|
||||||
|
NoActiveOrderError = 'NO_ACTIVE_ORDER_ERROR',
|
||||||
|
}
|
20
src/domains/interfaces/CommonError.ts
Normal file
20
src/domains/interfaces/CommonError.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { ErrorCode } from '../enums/ErrorCode'
|
||||||
|
|
||||||
|
// TODO: Can not find
|
||||||
|
// import { ErrorCode } from '@framework/schema'
|
||||||
|
|
||||||
|
export class CommonError {
|
||||||
|
message: string = ''
|
||||||
|
|
||||||
|
errorCode: ErrorCode = ErrorCode.UnknownError
|
||||||
|
|
||||||
|
error?: Error
|
||||||
|
|
||||||
|
static create(message: string, errorCode?: ErrorCode): CommonError {
|
||||||
|
const error = new CommonError()
|
||||||
|
error.message = message
|
||||||
|
error.errorCode = errorCode || ErrorCode.UnknownError
|
||||||
|
error.error = new Error()
|
||||||
|
return error
|
||||||
|
}
|
||||||
|
}
|
28
src/utils/fetcher.ts
Normal file
28
src/utils/fetcher.ts
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import { request } from 'graphql-request'
|
||||||
|
import { RequestDocument, Variables } from 'graphql-request/dist/types'
|
||||||
|
|
||||||
|
interface QueryOptions {
|
||||||
|
query: RequestDocument
|
||||||
|
variables?: Variables
|
||||||
|
onLoad?: (loading: boolean) => any
|
||||||
|
key?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetcher = async <T>(options: QueryOptions): Promise<T> => {
|
||||||
|
const { query, variables } = options
|
||||||
|
console.log('query')
|
||||||
|
console.log(options)
|
||||||
|
const token = localStorage.getItem('token')
|
||||||
|
console.log('token')
|
||||||
|
console.log(token)
|
||||||
|
const res = await request<T>(
|
||||||
|
process.env.NEXT_PUBLIC_VENDURE_SHOP_API_URL as string,
|
||||||
|
query,
|
||||||
|
variables,
|
||||||
|
token ? { Authorization: 'Bearer ' + token } : {}
|
||||||
|
)
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
export default fetcher
|
11
src/utils/gglFetcher.ts
Normal file
11
src/utils/gglFetcher.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { RequestDocument, Variables } from 'graphql-request/dist/types'
|
||||||
|
import fetcher from './fetcher'
|
||||||
|
|
||||||
|
const gglFetcher = async <T>(
|
||||||
|
...params: [RequestDocument, Variables]
|
||||||
|
): Promise<T> => {
|
||||||
|
const [query, variables] = params
|
||||||
|
return fetcher<T>({ query, variables })
|
||||||
|
}
|
||||||
|
|
||||||
|
export default gglFetcher
|
28
src/utils/rawFetcher.ts
Normal file
28
src/utils/rawFetcher.ts
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import { rawRequest } from 'graphql-request'
|
||||||
|
import { RequestDocument, Variables } from 'graphql-request/dist/types'
|
||||||
|
|
||||||
|
interface QueryOptions {
|
||||||
|
query: RequestDocument
|
||||||
|
variables?: Variables
|
||||||
|
onLoad?: (loading: boolean) => any
|
||||||
|
key?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const rawFetcher = <T>({
|
||||||
|
query,
|
||||||
|
variables,
|
||||||
|
onLoad = () => true,
|
||||||
|
}: QueryOptions): Promise<{ data: T; headers: any }> => {
|
||||||
|
onLoad(true)
|
||||||
|
return rawRequest<T>(
|
||||||
|
process.env.NEXT_PUBLIC_VENDURE_SHOP_API_URL as string,
|
||||||
|
query as string,
|
||||||
|
variables
|
||||||
|
)
|
||||||
|
.then(({ data, headers }) => {
|
||||||
|
return { data, headers }
|
||||||
|
})
|
||||||
|
.finally(() => onLoad(false))
|
||||||
|
}
|
||||||
|
|
||||||
|
export default rawFetcher
|
Reference in New Issue
Block a user