summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorit-fixcomart <it@fixcomart.co.id>2024-09-18 14:39:16 +0700
committerit-fixcomart <it@fixcomart.co.id>2024-09-18 14:39:16 +0700
commitb8b3b1df835d429920975e023d956b7c6ca33f43 (patch)
treed2488bf9c67d03ec5e9c686b17b0f994f3da6c77
parentab0782b5cf7b65930b0b40528b9205f3f0dfc3a0 (diff)
parentbaa9b1e32c0afabf074f6c181274312d757a7099 (diff)
Merge branch 'Feature/new-register' into Feature/switch-account
-rw-r--r--src-migrate/modules/register/components/Form.tsx56
-rw-r--r--src-migrate/modules/register/components/FormBisnis.tsx120
-rw-r--r--src-migrate/modules/register/components/RegistrasiBisnis.tsx8
-rw-r--r--src-migrate/modules/register/components/RegistrasiIndividu.tsx7
-rw-r--r--src-migrate/modules/register/index.tsx13
-rw-r--r--src/lib/address/components/Addresses.jsx140
-rw-r--r--src/lib/address/components/EditAddress.jsx414
-rw-r--r--src/lib/auth/components/CompanyProfile.jsx19
-rw-r--r--src/lib/checkout/components/Checkout.jsx3
-rw-r--r--src/pages/login.jsx12
-rw-r--r--src/pages/my/address/[id]/edit.jsx28
-rw-r--r--tsconfig.json18
12 files changed, 579 insertions, 259 deletions
diff --git a/src-migrate/modules/register/components/Form.tsx b/src-migrate/modules/register/components/Form.tsx
index 118d9d69..cd0b4343 100644
--- a/src-migrate/modules/register/components/Form.tsx
+++ b/src-migrate/modules/register/components/Form.tsx
@@ -1,4 +1,4 @@
-import { ChangeEvent, useMemo } from 'react';
+import { ChangeEvent, useMemo, useEffect, useRef, useState } from 'react';
import { useMutation } from 'react-query';
import { useRegisterStore } from '../stores/useRegisterStore';
import { RegisterProps } from '~/types/auth';
@@ -14,22 +14,28 @@ interface FormProps {
required: boolean;
isBisnisRegist: boolean;
chekValid: boolean;
+ buttonSubmitClick: boolean;
}
const Form: React.FC<FormProps> = ({
type,
required,
isBisnisRegist = false,
- chekValid = false,
+ chekValid,
+ buttonSubmitClick,
}) => {
const { form, isCheckedTNC, isValidCaptcha, errors, updateForm, validate } =
useRegisterStore();
-
const isFormValid = useMemo(() => Object.keys(errors).length === 0, [errors]);
const router = useRouter();
const toast = useToast();
+ const emailRef = useRef<HTMLInputElement>(null);
+ const nameRef = useRef<HTMLInputElement>(null);
+ const passwordRef = useRef<HTMLInputElement>(null);
+ const phoneRef = useRef<HTMLInputElement>(null);
+
const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => {
const { name, value } = event.target;
updateForm(name, value);
@@ -40,6 +46,38 @@ const Form: React.FC<FormProps> = ({
mutationFn: (data: RegisterProps) => registerUser(data),
});
+ useEffect(() => {
+ const loadIndustries = async () => {
+ const response = await mutation.mutateAsync(form);
+ if (!response?.register) {
+ const options: ScrollIntoViewOptions = {
+ behavior: 'smooth',
+ block: 'center',
+ };
+
+ if (errors.email_partner && emailRef.current) {
+ emailRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errors.name && nameRef.current) {
+ nameRef.current.scrollIntoView(options);
+ return;
+ }
+
+ if (errors.password && passwordRef.current) {
+ passwordRef.current.scrollIntoView(options);
+ return;
+ }
+
+ if (errors.phone && phoneRef.current) {
+ phoneRef.current.scrollIntoView(options);
+ return;
+ }
+ }
+ };
+ loadIndustries();
+ }, [buttonSubmitClick, chekValid]);
+
const handleSubmit = async (e: ChangeEvent<HTMLFormElement>) => {
e.preventDefault();
@@ -98,9 +136,10 @@ const Form: React.FC<FormProps> = ({
type='text'
id='name'
name='name'
- className='form-input mt-3'
+ className='form-input mt-3 transition-all duration-700'
placeholder='Masukan nama lengkap anda'
value={form.name}
+ ref={nameRef}
onChange={handleInputChange}
aria-invalid={chekValid && !!errors.name}
/>
@@ -119,9 +158,10 @@ const Form: React.FC<FormProps> = ({
type='text'
id='email'
name='email'
- className='form-input mt-3'
+ className='form-input mt-3 transition-all duration-500'
placeholder='Masukan alamat email anda'
value={form.email}
+ ref={emailRef}
onChange={handleInputChange}
autoComplete='username'
aria-invalid={chekValid && !!errors.email}
@@ -140,9 +180,10 @@ const Form: React.FC<FormProps> = ({
type='password'
name='password'
id='password'
- className='form-input mt-3'
+ className='form-input mt-3 transition-all duration-500'
placeholder='••••••••••••'
value={form.password}
+ ref={passwordRef}
onChange={handleInputChange}
autoComplete='current-password'
aria-invalid={chekValid && !!errors.password}
@@ -162,9 +203,10 @@ const Form: React.FC<FormProps> = ({
type='tel'
id='phone'
name='phone'
- className='form-input mt-3'
+ className='form-input mt-3 transition-all duration-500'
placeholder='08xxxxxxxx'
value={form.phone}
+ ref={phoneRef}
onChange={handleInputChange}
aria-invalid={chekValid && !!errors.phone}
/>
diff --git a/src-migrate/modules/register/components/FormBisnis.tsx b/src-migrate/modules/register/components/FormBisnis.tsx
index 85bb491d..b81ca601 100644
--- a/src-migrate/modules/register/components/FormBisnis.tsx
+++ b/src-migrate/modules/register/components/FormBisnis.tsx
@@ -1,4 +1,4 @@
-import { ChangeEvent, useEffect, useMemo, useState } from 'react';
+import { ChangeEvent, useEffect, useMemo, useRef, useState } from 'react';
import { useMutation } from 'react-query';
import { useRegisterStore } from '../stores/useRegisterStore';
import { RegisterProps } from '~/types/auth';
@@ -26,6 +26,7 @@ interface FormProps {
required: boolean;
isPKP: boolean;
chekValid: boolean;
+ buttonSubmitClick: boolean;
}
interface industry_id {
@@ -39,7 +40,13 @@ interface companyType {
label: string;
}
-const form: React.FC<FormProps> = ({ type, required, isPKP, chekValid }) => {
+const form: React.FC<FormProps> = ({
+ type,
+ required,
+ isPKP,
+ chekValid,
+ buttonSubmitClick,
+}) => {
const { form, errors, updateForm, validate } = useRegisterStore();
const { control, watch, setValue } = useForm();
const [selectedCategory, setSelectedCategory] = useState<string>('');
@@ -56,6 +63,18 @@ const form: React.FC<FormProps> = ({ type, required, isPKP, chekValid }) => {
const router = useRouter();
const toast = useToast();
+ const emailRef = useRef<HTMLInputElement>(null);
+ const businessNameRef = useRef<HTMLInputElement>(null);
+ const companyTypeRef = useRef<HTMLInputElement>(null);
+ const industryRef = useRef<HTMLDivElement>(null);
+ const addressRef = useRef<HTMLInputElement>(null);
+ const namaWajibPajakRef = useRef<HTMLInputElement>(null);
+ const alamatWajibPajakRef = useRef<HTMLInputElement>(null);
+ const npwpRef = useRef<HTMLInputElement>(null);
+ const sppkpRef = useRef<HTMLInputElement>(null);
+ const docsSppkpRef = useRef<HTMLInputElement>(null);
+ const docsNpwpRef = useRef<HTMLInputElement>(null);
+
useEffect(() => {
const loadCompanyTypes = async () => {
const dataCompanyTypes = await odooApi(
@@ -227,6 +246,60 @@ const form: React.FC<FormProps> = ({ type, required, isPKP, chekValid }) => {
mutationFn: (data: RegisterProps) => registerUser(data),
});
+ useEffect(() => {
+ const loadIndustries = async () => {
+ const response = await mutation.mutateAsync(form);
+ if (!response?.register) {
+ const options: ScrollIntoViewOptions = {
+ behavior: 'smooth',
+ block: 'center',
+ };
+ if (errors.email_partner && emailRef.current) {
+ emailRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errors.company_type_id && companyTypeRef.current) {
+ companyTypeRef.current.scrollIntoView(options);
+ return;
+ }
+
+ if (errors.business_name && businessNameRef.current) {
+ businessNameRef.current.scrollIntoView(options);
+ return;
+ }
+
+ if (errors.industry_id && industryRef.current) {
+ industryRef.current.scrollIntoView(options);
+ return;
+ }
+
+ if (errors.alamat_bisnis && addressRef.current) {
+ addressRef.current.scrollIntoView(options);
+ return;
+ }
+
+ if (errors.npwp && npwpRef.current) {
+ npwpRef.current.scrollIntoView(options);
+ return;
+ }
+
+ if (errors.sppkp && sppkpRef.current) {
+ sppkpRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errors.sppkp_document && docsSppkpRef.current) {
+ docsSppkpRef.current.scrollIntoView(options);
+ return;
+ }
+ if (errors.npwp_document && docsNpwpRef.current) {
+ docsNpwpRef.current.scrollIntoView(options);
+ return;
+ }
+ }
+ };
+ loadIndustries();
+ }, [buttonSubmitClick, chekValid]);
+
const handleSubmit = async (e: ChangeEvent<HTMLFormElement>) => {
e.preventDefault();
@@ -314,7 +387,7 @@ const form: React.FC<FormProps> = ({ type, required, isPKP, chekValid }) => {
name='email_partner'
placeholder='example@email.com'
value={!required ? form.email_partner : ''}
- className={`form-input max-h-11 mt-3 ${
+ className={`form-input max-h-11 mt-3 transition-all duration-500 ${
required ? 'cursor-no-drop' : ''
}`}
disabled={required}
@@ -322,6 +395,7 @@ const form: React.FC<FormProps> = ({ type, required, isPKP, chekValid }) => {
readOnly={required}
onChange={handleInputChange}
autoComplete='username'
+ ref={emailRef}
aria-invalid={
chekValid && !required && isPKP && !!errors.email_partner
}
@@ -332,12 +406,15 @@ const form: React.FC<FormProps> = ({ type, required, isPKP, chekValid }) => {
)}
</div>
- <div className=''>
+ <div>
<label className='font-bold' htmlFor='company'>
Nama Bisnis
</label>
- <div className='flex justify-between items-start gap-2 max-h-11 min-h-11 text-sm mt-3'>
- <div className='w-4/5 pr-1 max-h-11'>
+ <div className='flex justify-between items-start gap-2 max-h-12 min-h-12 text-sm mt-3'>
+ <div
+ className='w-4/5 pr-1 max-h-11 transition-all duration-500'
+ ref={companyTypeRef}
+ >
<Controller
name='companyType'
control={control}
@@ -361,10 +438,11 @@ const form: React.FC<FormProps> = ({ type, required, isPKP, chekValid }) => {
type='text'
name='business_name'
id='business_name'
- className='form-input max-h-11'
+ className='form-input max-h-11 transition-all duration-500'
placeholder='Nama Perusahaan'
autoCapitalize='true'
value={form.business_name}
+ ref={businessNameRef}
aria-invalid={chekValid && !!errors.business_name}
onChange={handleInputChange}
/>
@@ -380,7 +458,10 @@ const form: React.FC<FormProps> = ({ type, required, isPKP, chekValid }) => {
<label className='font-bold' htmlFor='business_name'>
Klasifikasi Jenis Usaha
</label>
- <div className='max-h-10 mt-3'>
+ <div
+ className='max-h-10 transition-all duration-500'
+ ref={industryRef}
+ >
<Controller
name='industry_id'
control={control}
@@ -415,12 +496,13 @@ const form: React.FC<FormProps> = ({ type, required, isPKP, chekValid }) => {
name='alamat_bisnis'
placeholder='Masukan alamat bisnis anda'
value={!required ? form.alamat_bisnis : ''}
- className={`form-input mt-3 max-h-11 ${
+ className={`form-input mt-3 max-h-11 transition-all duration-500 ${
required ? 'cursor-no-drop' : ''
}`}
disabled={required}
contentEditable={required}
readOnly={required}
+ ref={addressRef}
onChange={handleInputChange}
aria-invalid={chekValid && !required && !!errors.alamat_bisnis}
/>
@@ -444,13 +526,14 @@ const form: React.FC<FormProps> = ({ type, required, isPKP, chekValid }) => {
name='nama_wajib_pajak'
placeholder='Masukan nama lengkap anda'
value={!required ? form.nama_wajib_pajak : ''}
- className={`form-input mt-3 max-h-11 ${
+ className={`form-input mt-3 max-h-11 transition-all duration-500${
required ? 'cursor-no-drop' : ''
}`}
disabled={required}
contentEditable={required}
readOnly={required}
onChange={handleInputChange}
+ ref={namaWajibPajakRef}
aria-invalid={
chekValid && isPKP && !required && !!errors.nama_wajib_pajak
}
@@ -472,7 +555,7 @@ const form: React.FC<FormProps> = ({ type, required, isPKP, chekValid }) => {
<span className='font-normal text-gray_r-11'>(opsional)</span>
)}
</p>
- <div className='flex items-center ml-2 mt-1'>
+ <div className='flex items-center ml-2 mt-1 '>
<Checkbox
borderColor='gray.600'
colorScheme='red'
@@ -498,13 +581,14 @@ const form: React.FC<FormProps> = ({ type, required, isPKP, chekValid }) => {
: form.alamat_wajib_pajak
: ''
}
- className={`form-input max-h-11 mt-3 ${
+ className={`form-input max-h-11 mt-3 transition-all duration-500 ${
required ? 'cursor-no-drop' : ''
}`}
disabled={isChekBox || required}
contentEditable={required}
readOnly={required}
onChange={handleInputChange}
+ ref={alamatWajibPajakRef}
aria-invalid={
chekValid && isPKP && !required && !!errors.alamat_wajib_pajak
}
@@ -527,12 +611,13 @@ const form: React.FC<FormProps> = ({ type, required, isPKP, chekValid }) => {
type='tel'
id='npwp'
name='npwp'
- className={`form-input max-h-11 mt-3 ${
+ className={`form-input max-h-11 mt-3 transition-all duration-500 ${
required ? 'cursor-no-drop' : ''
}`}
disabled={required}
contentEditable={required}
readOnly={required}
+ ref={npwpRef}
placeholder='000.000.000.0-000.000'
value={!required ? formattedNpwp : ''}
maxLength={21} // Set maximum length to 16 characters
@@ -586,12 +671,13 @@ const form: React.FC<FormProps> = ({ type, required, isPKP, chekValid }) => {
type='tel'
id='sppkp'
name='sppkp'
- className={`form-input max-h-11 mt-3 ${
+ className={`form-input max-h-11 mt-3 transition-all duration-500 ${
required ? 'cursor-no-drop' : ''
}`}
disabled={required}
contentEditable={required}
readOnly={required}
+ ref={sppkpRef}
placeholder='X-XXXPKP/WJPXXX/XX.XXXX/XXXX'
onChange={handleInputChange}
value={!required ? form.sppkp : ''}
@@ -615,11 +701,12 @@ const form: React.FC<FormProps> = ({ type, required, isPKP, chekValid }) => {
type='file'
id='npwp_document'
name='npwp_document'
- className={`form-input ${
+ className={`form-input transition-all duration-500 ${
type === 'bisnis' ? '' : 'border-none'
} mt-3 ${required ? 'cursor-no-drop' : ''}`}
disabled={required}
contentEditable={required}
+ ref={docsNpwpRef}
readOnly={required}
onChange={handleFileChange}
accept='.pdf,.doc,.docx,.png,.jpg,.jpeg' // Filter file types
@@ -642,11 +729,12 @@ const form: React.FC<FormProps> = ({ type, required, isPKP, chekValid }) => {
type='file'
id='sppkp_document'
name='sppkp_document'
- className={`form-input ${
+ className={`form-input transition-all duration-500 ${
type === 'bisnis' ? '' : 'border-none'
} mt-3 ${required ? 'cursor-no-drop' : ''}`}
disabled={required}
contentEditable={required}
+ ref={docsSppkpRef}
readOnly={required}
onChange={handleFileChange}
accept='.pdf,.doc,.docx,.png,.jpg,.jpeg' // Filter file types
diff --git a/src-migrate/modules/register/components/RegistrasiBisnis.tsx b/src-migrate/modules/register/components/RegistrasiBisnis.tsx
index 36476ab9..ce4d3972 100644
--- a/src-migrate/modules/register/components/RegistrasiBisnis.tsx
+++ b/src-migrate/modules/register/components/RegistrasiBisnis.tsx
@@ -16,8 +16,12 @@ import { UseToastOptions, useToast } from '@chakra-ui/react';
import Link from 'next/link';
interface FormProps {
chekValid: boolean;
+ buttonSubmitClick: boolean;
}
-const RegistrasiBisnis: React.FC<FormProps> = ({ chekValid }) => {
+const RegistrasiBisnis: React.FC<FormProps> = ({
+ chekValid,
+ buttonSubmitClick,
+}) => {
const [isPKP, setIsPKP] = useState(true);
const [isTerdaftar, setIsTerdaftar] = useState(false);
const [isDropIndividu, setIsDropIndividu] = useState(true);
@@ -113,6 +117,7 @@ const RegistrasiBisnis: React.FC<FormProps> = ({ chekValid }) => {
required={true}
isBisnisRegist={true}
chekValid={chekValid}
+ buttonSubmitClick={buttonSubmitClick}
/>
</div>
)}
@@ -177,6 +182,7 @@ const RegistrasiBisnis: React.FC<FormProps> = ({ chekValid }) => {
required={isTerdaftar}
isPKP={isPKP}
chekValid={chekValid}
+ buttonSubmitClick={buttonSubmitClick}
/>
</div>
)}
diff --git a/src-migrate/modules/register/components/RegistrasiIndividu.tsx b/src-migrate/modules/register/components/RegistrasiIndividu.tsx
index 3997e767..84049065 100644
--- a/src-migrate/modules/register/components/RegistrasiIndividu.tsx
+++ b/src-migrate/modules/register/components/RegistrasiIndividu.tsx
@@ -3,8 +3,12 @@ import { useRegisterStore } from '../stores/useRegisterStore';
import { useEffect } from 'react';
interface FormProps {
chekValid: boolean;
+ buttonSubmitClick: boolean;
}
-const RegistrasiIndividu: React.FC<FormProps> = ({ chekValid }) => {
+const RegistrasiIndividu: React.FC<FormProps> = ({
+ chekValid,
+ buttonSubmitClick,
+}) => {
const { form, errors, updateForm, validate } = useRegisterStore();
useEffect(() => {
@@ -21,6 +25,7 @@ const RegistrasiIndividu: React.FC<FormProps> = ({ chekValid }) => {
required={false}
isBisnisRegist={false}
chekValid={chekValid}
+ buttonSubmitClick={buttonSubmitClick}
/>
</>
);
diff --git a/src-migrate/modules/register/index.tsx b/src-migrate/modules/register/index.tsx
index d91af9e3..08d7f893 100644
--- a/src-migrate/modules/register/index.tsx
+++ b/src-migrate/modules/register/index.tsx
@@ -22,6 +22,7 @@ const LOGO_HEIGHT = LOGO_WIDTH / 3;
const Register = () => {
const [isIndividuClicked, setIsIndividuClicked] = useState(true);
const [notValid, setNotValid] = useState(false);
+ const [buttonSubmitClick, setButtonSubmitClick] = useState(false);
const [isBisnisClicked, setIsBisnisClicked] = useState(false);
const { form, isCheckedTNC, isValidCaptcha, resetForm, errors, updateForm } =
useRegisterStore();
@@ -49,8 +50,10 @@ const Register = () => {
const handleSubmit = async () => {
if (!isFormValid) {
setNotValid(true);
+ setButtonSubmitClick(!buttonSubmitClick);
return;
} else {
+ setButtonSubmitClick(!buttonSubmitClick);
setNotValid(false);
}
const response = await mutation.mutateAsync(form);
@@ -142,12 +145,18 @@ const Register = () => {
<div className='transition-opacity duration-300 ease-in-out'>
{isIndividuClicked && (
<div className='opacity-100'>
- <RegistrasiIndividu chekValid={notValid} />
+ <RegistrasiIndividu
+ chekValid={notValid}
+ buttonSubmitClick={buttonSubmitClick}
+ />
</div>
)}
{isBisnisClicked && (
<div className='opacity-100'>
- <RegistrasiBisnis chekValid={notValid} />
+ <RegistrasiBisnis
+ chekValid={notValid}
+ buttonSubmitClick={buttonSubmitClick}
+ />
</div>
)}
</div>
diff --git a/src/lib/address/components/Addresses.jsx b/src/lib/address/components/Addresses.jsx
index a610d371..9ca617ae 100644
--- a/src/lib/address/components/Addresses.jsx
+++ b/src/lib/address/components/Addresses.jsx
@@ -1,34 +1,72 @@
-import Link from '@/core/components/elements/Link/Link'
-import Spinner from '@/core/components/elements/Spinner/Spinner'
-import useAuth from '@/core/hooks/useAuth'
-import { getItemAddress, updateItemAddress } from '@/core/utils/address'
-import { useRouter } from 'next/router'
-import useAddresses from '../hooks/useAddresses'
-import MobileView from '@/core/components/views/MobileView'
-import DesktopView from '@/core/components/views/DesktopView'
-import Menu from '@/lib/auth/components/Menu'
+import { useState } from 'react';
+import Link from '@/core/components/elements/Link/Link';
+import Spinner from '@/core/components/elements/Spinner/Spinner';
+import useAuth from '@/core/hooks/useAuth';
+import { getItemAddress, updateItemAddress } from '@/core/utils/address';
+import { useRouter } from 'next/router';
+import useAddresses from '../hooks/useAddresses';
+import MobileView from '@/core/components/views/MobileView';
+import DesktopView from '@/core/components/views/DesktopView';
+import Menu from '@/lib/auth/components/Menu';
+import BottomPopup from '@/core/components/elements/Popup/BottomPopup';
const Addresses = () => {
- const router = useRouter()
- const { select = null } = router.query
- const { addresses } = useAddresses()
- const selectedAddress = getItemAddress(select || '')
+ const router = useRouter();
+ const { select = null } = router.query;
+ const { addresses } = useAddresses();
+ const selectedAddress = getItemAddress(select || '');
+ const [changeConfirmation, setChangeConfirmation] = useState(false);
+ const [selectedForChange, setSelectedForChange] = useState(null); // State baru untuk simpan alamat yang akan diubah
+
const changeSelectedAddress = (id) => {
- if (!select) return
- updateItemAddress(select, id)
- router.back()
- }
+ if (!select) return;
+ updateItemAddress(select, id);
+ router.back();
+ };
+
+ const handleConfirmSubmit = () => {
+ setChangeConfirmation(false);
+ if (selectedForChange) {
+ router.push(`/my/address/${selectedForChange}/edit`);
+ }
+ };
if (addresses.isLoading) {
return (
<div className='flex justify-center my-6'>
<Spinner className='w-6 text-gray_r-12/50 fill-gray_r-12' />
</div>
- )
+ );
}
return (
<>
+ <BottomPopup
+ active={changeConfirmation}
+ close={() => setChangeConfirmation(false)} // Menutup popup
+ title='Ubah alamat Bisnis'
+ >
+ <div className='leading-7 text-gray_r-12/80'>
+ Anda akan mengubah alamat utama bisnis?
+ </div>
+ <div className='flex mt-6 gap-x-4 md:justify-end'>
+ <button
+ className='btn-solid-red flex-1 md:flex-none'
+ type='button'
+ onClick={handleConfirmSubmit}
+ >
+ Yakin
+ </button>
+ <button
+ className='btn-light flex-1 md:flex-none'
+ type='button'
+ onClick={() => setChangeConfirmation(false)}
+ >
+ Batal
+ </button>
+ </div>
+ </BottomPopup>
+
<MobileView>
<div className='p-4'>
<div className='text-right'>
@@ -37,7 +75,10 @@ const Addresses = () => {
<div className='grid gap-y-4 mt-4'>
{addresses.data?.map((address, index) => {
- const type = address.type.charAt(0).toUpperCase() + address.type.slice(1) + ' Address'
+ const type =
+ address.type.charAt(0).toUpperCase() +
+ address.type.slice(1) +
+ ' Address';
return (
<AddressCard
key={index}
@@ -45,9 +86,11 @@ const Addresses = () => {
type={type}
changeSelectedAddress={changeSelectedAddress}
selectedAddress={selectedAddress}
+ setChangeConfirmation={setChangeConfirmation} // Memanggil popup
+ setSelectedForChange={setSelectedForChange} // Simpan id address yang akan diubah
select={select}
/>
- )
+ );
})}
</div>
</div>
@@ -72,7 +115,9 @@ const Addresses = () => {
<div className='grid grid-cols-2 gap-4'>
{addresses.data?.map((address, index) => {
const type =
- address.type.charAt(0).toUpperCase() + address.type.slice(1) + ' Address'
+ address.type.charAt(0).toUpperCase() +
+ address.type.slice(1) +
+ ' Address';
return (
<AddressCard
key={index}
@@ -80,20 +125,31 @@ const Addresses = () => {
type={type}
changeSelectedAddress={changeSelectedAddress}
selectedAddress={selectedAddress}
+ setChangeConfirmation={setChangeConfirmation}
+ setSelectedForChange={setSelectedForChange}
select={select}
/>
- )
+ );
})}
</div>
</div>
</div>
</DesktopView>
</>
- )
-}
+ );
+};
-const AddressCard = ({ address, selectedAddress, changeSelectedAddress, type, select }) => {
- const auth = useAuth()
+const AddressCard = ({
+ address,
+ selectedAddress,
+ changeSelectedAddress,
+ type,
+ select,
+ setChangeConfirmation,
+ setSelectedForChange,
+}) => {
+ const auth = useAuth();
+ const router = useRouter();
return (
<div
@@ -106,23 +162,37 @@ const AddressCard = ({ address, selectedAddress, changeSelectedAddress, type, se
(select && 'cursor-pointer hover:bg-gray_r-4 transition')
}`}
>
- <div onClick={() => changeSelectedAddress(address.id)} className={select && 'cursor-pointer'}>
+ <div
+ onClick={() => changeSelectedAddress(address.id)}
+ className={select && 'cursor-pointer'}
+ >
<div className='flex gap-x-2'>
<div className='badge-red'>{type}</div>
- {auth?.partnerId == address.id && <div className='badge-green'>Utama</div>}
+ {auth?.partnerId == address.id && (
+ <div className='badge-green'>Utama</div>
+ )}
</div>
<p className='font-medium mt-2'>{address.name}</p>
- {address.mobile && <p className='mt-2 text-gray_r-11'>{address.mobile}</p>}
+ {address.mobile && (
+ <p className='mt-2 text-gray_r-11'>{address.mobile}</p>
+ )}
<p className='mt-1 leading-6 text-gray_r-11'>{address.street}</p>
</div>
- <Link
- href={`/my/address/${address.id}/edit`}
+ <button
+ onClick={() => {
+ if (type == 'Contact Address' && auth.parentId) {
+ setSelectedForChange(address.id); // Set alamat yang dipilih
+ setChangeConfirmation(true); // Tampilkan popup konfirmasi
+ } else {
+ router.push(`/my/address/${address.id}/edit`);
+ }
+ }}
className='btn-light bg-white mt-3 w-full !text-gray_r-11'
>
Ubah Alamat
- </Link>
+ </button>
</div>
- )
-}
+ );
+};
-export default Addresses
+export default Addresses;
diff --git a/src/lib/address/components/EditAddress.jsx b/src/lib/address/components/EditAddress.jsx
index 520bba51..580aaeb8 100644
--- a/src/lib/address/components/EditAddress.jsx
+++ b/src/lib/address/components/EditAddress.jsx
@@ -1,18 +1,22 @@
-import { yupResolver } from '@hookform/resolvers/yup'
-import { useRouter } from 'next/router'
-import { useEffect, useState } from 'react'
-import * as Yup from 'yup'
-import cityApi from '../api/cityApi'
-import { Controller, useForm } from 'react-hook-form'
-import districtApi from '../api/districtApi'
-import subDistrictApi from '../api/subDistrictApi'
-import editAddressApi from '../api/editAddressApi'
-import HookFormSelect from '@/core/components/elements/Select/HookFormSelect'
-import { toast } from 'react-hot-toast'
-import Menu from '@/lib/auth/components/Menu'
+import { yupResolver } from '@hookform/resolvers/yup';
+import { useRouter } from 'next/router';
+import { useEffect, useState } from 'react';
+import * as Yup from 'yup';
+import cityApi from '../api/cityApi';
+import { Controller, useForm } from 'react-hook-form';
+import districtApi from '../api/districtApi';
+import subDistrictApi from '../api/subDistrictApi';
+import addressApi from '@/lib/address/api/addressApi';
+import editAddressApi from '../api/editAddressApi';
+import HookFormSelect from '@/core/components/elements/Select/HookFormSelect';
+import { toast } from 'react-hot-toast';
+import Menu from '@/lib/auth/components/Menu';
+import useAuth from '@/core/hooks/useAuth';
+import odooApi from '@/core/api/odooApi';
const EditAddress = ({ id, defaultValues }) => {
- const router = useRouter()
+ const auth = useAuth();
+ const router = useRouter();
const {
register,
formState: { errors },
@@ -20,205 +24,281 @@ const EditAddress = ({ id, defaultValues }) => {
watch,
setValue,
getValues,
- control
+ control,
} = useForm({
resolver: yupResolver(validationSchema),
- defaultValues
- })
+ defaultValues,
+ });
- const [cities, setCities] = useState([])
- const [districts, setDistricts] = useState([])
- const [subDistricts, setSubDistricts] = useState([])
+ const [cities, setCities] = useState([]);
+ const [districts, setDistricts] = useState([]);
+ const [subDistricts, setSubDistricts] = useState([]);
+
+ useEffect(() => {
+ const loadProfile = async () => {
+ const dataProfile = await addressApi({ id: auth.parentId });
+ setValue('industry', dataProfile.industryId);
+ setValue('companyType', dataProfile.companyTypeId);
+ setValue('taxName', dataProfile.taxName);
+ setValue('npwp', dataProfile.npwp);
+ setValue('alamat_wajib_pajak', dataProfile.alamatWajibPajak);
+ setValue('alamat_bisnis', dataProfile.alamatBisnis);
+ };
+ if (auth) loadProfile();
+ }, [auth, setValue]);
useEffect(() => {
const loadCities = async () => {
- let dataCities = await cityApi()
+ let dataCities = await cityApi();
dataCities = dataCities.map((city) => ({
value: city.id,
- label: city.name
- }))
- setCities(dataCities)
- }
- loadCities()
- }, [])
+ label: city.name,
+ }));
+ setCities(dataCities);
+ };
+ loadCities();
+ }, []);
- const watchCity = watch('city')
+ const watchCity = watch('city');
useEffect(() => {
- setValue('district', '')
+ setValue('district', '');
if (watchCity) {
const loadDistricts = async () => {
- let dataDistricts = await districtApi({ cityId: watchCity })
+ let dataDistricts = await districtApi({ cityId: watchCity });
dataDistricts = dataDistricts.map((district) => ({
value: district.id,
- label: district.name
- }))
- setDistricts(dataDistricts)
- let oldDistrict = getValues('oldDistrict')
+ label: district.name,
+ }));
+ setDistricts(dataDistricts);
+ let oldDistrict = getValues('oldDistrict');
if (oldDistrict) {
- setValue('district', oldDistrict)
- setValue('oldDistrict', '')
+ setValue('district', oldDistrict);
+ setValue('oldDistrict', '');
}
- }
- loadDistricts()
+ };
+ loadDistricts();
}
- }, [watchCity, setValue, getValues])
+ }, [watchCity, setValue, getValues]);
- const watchDistrict = watch('district')
+ const watchDistrict = watch('district');
useEffect(() => {
- setValue('subDistrict', '')
+ setValue('subDistrict', '');
if (watchDistrict) {
const loadSubDistricts = async () => {
let dataSubDistricts = await subDistrictApi({
- districtId: watchDistrict
- })
+ districtId: watchDistrict,
+ });
dataSubDistricts = dataSubDistricts.map((district) => ({
value: district.id,
- label: district.name
- }))
- setSubDistricts(dataSubDistricts)
- let oldSubDistrict = getValues('oldSubDistrict')
+ label: district.name,
+ }));
+ setSubDistricts(dataSubDistricts);
+ let oldSubDistrict = getValues('oldSubDistrict');
if (oldSubDistrict) {
- setValue('subDistrict', oldSubDistrict)
- setValue('oldSubDistrict', '')
+ setValue('subDistrict', oldSubDistrict);
+ setValue('oldSubDistrict', '');
}
- }
- loadSubDistricts()
+ };
+ loadSubDistricts();
}
- }, [watchDistrict, setValue, getValues])
+ }, [watchDistrict, setValue, getValues]);
const onSubmitHandler = async (values) => {
const data = {
...values,
+ phone: values.mobile,
city_id: values.city,
district_id: values.district,
- sub_district_id: values.subDistrict
+ sub_district_id: values.subDistrict,
+ };
+ const address = await editAddressApi({ id, data });
+ let dataAlamat;
+ let isUpdated = true;
+ if (auth?.partnerId == id) {
+ dataAlamat = {
+ ...values,
+ id_user: auth.partnerId,
+ company_type_id: values.companyType,
+ industry_id: values.industry,
+ tax_name: values.taxName,
+ alamat_lengkap_text: values.alamat_wajib_pajak,
+ street: values.street,
+ };
+ isUpdated = await odooApi(
+ 'PUT',
+ `/api/v1/partner/${auth.parentId}`,
+ dataAlamat
+ );
}
- const address = await editAddressApi({ id, data })
+ // if (isUpdated?.id) {
if (address?.id) {
- toast.success('Berhasil mengubah alamat')
- router.back()
+ toast.success('Berhasil mengubah alamat');
+ router.back();
+ } else {
+ toast.error('Terjadi kesalahan internal');
+ router.back();
}
- }
+ };
return (
- <div className='max-w-none md:container mx-auto flex p-0 md:py-10'>
- <div className='hidden md:block w-3/12 pr-4'>
- <Menu />
- </div>
- <div className='w-full md:w-9/12 p-4 bg-white border border-gray_r-6 rounded'>
- <h1 className='text-title-sm font-semibold mb-6 hidden md:block'>Ubah Alamat</h1>
- <form onSubmit={handleSubmit(onSubmitHandler)}>
- <div className='grid grid-cols-1 md:grid-cols-2 gap-4'>
- <div>
- <label className='form-label mb-2'>Label Alamat</label>
- <Controller
- name='type'
- control={control}
- render={(props) => (
- <HookFormSelect {...props} isSearchable={false} options={types} />
- )}
- />
- <div className='text-caption-2 text-danger-500 mt-1'>{errors.type?.message}</div>
- </div>
+ <>
+ <div className='max-w-none md:container mx-auto flex p-0 md:py-10'>
+ <div className='hidden md:block w-3/12 pr-4'>
+ <Menu />
+ </div>
+ <div className='w-full md:w-9/12 p-4 bg-white border border-gray_r-6 rounded'>
+ <div className='flex justify-start items-center mb-6'>
+ <h1 className='text-title-sm font-semibold hidden md:block mr-2'>
+ Ubah Alamat
+ </h1>
+ {auth?.partnerId == id && <div className='badge-green'>Utama</div>}
+ </div>
+ <form onSubmit={handleSubmit(onSubmitHandler)}>
+ <div className='grid grid-cols-1 md:grid-cols-2 gap-4'>
+ <div>
+ <label className='form-label mb-2'>Label Alamat</label>
+ <Controller
+ name='type'
+ control={control}
+ render={(props) => (
+ <HookFormSelect
+ {...props}
+ isSearchable={false}
+ options={types}
+ />
+ )}
+ />
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.type?.message}
+ </div>
+ </div>
- <div>
- <label className='form-label mb-2'>Nama</label>
- <input
- {...register('name')}
- placeholder='John Doe'
- type='text'
- className='form-input'
- />
- <div className='text-caption-2 text-danger-500 mt-1'>{errors.name?.message}</div>
- </div>
+ <div>
+ <label className='form-label mb-2'>Nama</label>
+ <input
+ {...register('name')}
+ placeholder='John Doe'
+ type='text'
+ className='form-input'
+ />
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.name?.message}
+ </div>
+ </div>
- <div>
- <label className='form-label mb-2'>Email</label>
- <input
- {...register('email')}
- placeholder='johndoe@example.com'
- type='email'
- className='form-input'
- />
- <div className='text-caption-2 text-danger-500 mt-1'>{errors.email?.message}</div>
- </div>
+ <div>
+ <label className='form-label mb-2'>Email</label>
+ <input
+ {...register('email')}
+ placeholder='johndoe@example.com'
+ type='email'
+ className='form-input'
+ />
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.email?.message}
+ </div>
+ </div>
- <div>
- <label className='form-label mb-2'>Mobile</label>
- <input
- {...register('mobile')}
- placeholder='08xxxxxxxx'
- type='tel'
- className='form-input'
- />
- <div className='text-caption-2 text-danger-500 mt-1'>{errors.mobile?.message}</div>
- </div>
+ <div>
+ <label className='form-label mb-2'>Mobile</label>
+ <input
+ {...register('mobile')}
+ placeholder='08xxxxxxxx'
+ type='tel'
+ className='form-input'
+ />
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.mobile?.message}
+ </div>
+ </div>
- <div>
- <label className='form-label mb-2'>Alamat</label>
- <input
- {...register('street')}
- placeholder='Jl. Bandengan Utara 85A'
- type='text'
- className='form-input'
- />
- <div className='text-caption-2 text-danger-500 mt-1'>{errors.street?.message}</div>
- </div>
+ <div>
+ <label className='form-label mb-2'>Alamat</label>
+ <input
+ {...register('street')}
+ placeholder='Jl. Bandengan Utara 85A'
+ type='text'
+ className='form-input'
+ />
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.street?.message}
+ </div>
+ </div>
- <div>
- <label className='form-label mb-2'>Kode Pos</label>
- <input
- {...register('zip')}
- placeholder='10100'
- type='number'
- className='form-input'
- />
- <div className='text-caption-2 text-danger-500 mt-1'>{errors.zip?.message}</div>
- </div>
+ <div>
+ <label className='form-label mb-2'>Kode Pos</label>
+ <input
+ {...register('zip')}
+ placeholder='10100'
+ type='number'
+ className='form-input'
+ />
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.zip?.message}
+ </div>
+ </div>
- <div>
- <label className='form-label mb-2'>Kota</label>
- <Controller
- name='city'
- control={control}
- render={(props) => <HookFormSelect {...props} options={cities} />}
- />
- <div className='text-caption-2 text-danger-500 mt-1'>{errors.city?.message}</div>
- </div>
+ <div>
+ <label className='form-label mb-2'>Kota</label>
+ <Controller
+ name='city'
+ control={control}
+ render={(props) => (
+ <HookFormSelect {...props} options={cities} />
+ )}
+ />
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.city?.message}
+ </div>
+ </div>
- <div>
- <label className='form-label mb-2'>Kecamatan</label>
- <Controller
- name='district'
- control={control}
- render={(props) => (
- <HookFormSelect {...props} options={districts} disabled={!watchCity} />
- )}
- />
- <div className='text-caption-2 text-danger-500 mt-1'>{errors.district?.message}</div>
- </div>
+ <div>
+ <label className='form-label mb-2'>Kecamatan</label>
+ <Controller
+ name='district'
+ control={control}
+ render={(props) => (
+ <HookFormSelect
+ {...props}
+ options={districts}
+ disabled={!watchCity}
+ />
+ )}
+ />
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.district?.message}
+ </div>
+ </div>
- <div>
- <label className='form-label mb-2'>Kelurahan</label>
- <Controller
- name='subDistrict'
- control={control}
- render={(props) => (
- <HookFormSelect {...props} options={subDistricts} disabled={!watchDistrict} />
- )}
- />
+ <div>
+ <label className='form-label mb-2'>Kelurahan</label>
+ <Controller
+ name='subDistrict'
+ control={control}
+ render={(props) => (
+ <HookFormSelect
+ {...props}
+ options={subDistricts}
+ disabled={!watchDistrict}
+ />
+ )}
+ />
+ </div>
</div>
- </div>
- <button type='submit' className='btn-yellow w-full md:w-fit mt-6 ml-0 md:ml-auto'>
- Simpan
- </button>
- </form>
+ <button
+ type='submit'
+ className='btn-yellow w-full md:w-fit mt-6 ml-0 md:ml-auto'
+ >
+ Simpan
+ </button>
+ </form>
+ </div>
</div>
- </div>
- )
-}
+ </>
+ );
+};
const validationSchema = Yup.object().shape({
type: Yup.string().required('Harus di-pilih'),
@@ -228,14 +308,14 @@ const validationSchema = Yup.object().shape({
street: Yup.string().required('Harus di-isi'),
zip: Yup.string().required('Harus di-isi'),
city: Yup.string().required('Harus di-pilih'),
- district: Yup.string().required('Harus di-pilih')
-})
+ district: Yup.string().required('Harus di-pilih'),
+});
const types = [
{ value: 'contact', label: 'Contact Address' },
{ value: 'invoice', label: 'Invoice Address' },
{ value: 'delivery', label: 'Delivery Address' },
- { value: 'other', label: 'Other Address' }
-]
+ { value: 'other', label: 'Other Address' },
+];
-export default EditAddress
+export default EditAddress;
diff --git a/src/lib/auth/components/CompanyProfile.jsx b/src/lib/auth/components/CompanyProfile.jsx
index 20be6829..cebb15b0 100644
--- a/src/lib/auth/components/CompanyProfile.jsx
+++ b/src/lib/auth/components/CompanyProfile.jsx
@@ -21,9 +21,9 @@ const CompanyProfile = () => {
taxName: '',
npwp: '',
alamat_wajib_pajak: '',
+ alamat_bisnis: '',
},
});
-
const [industries, setIndustries] = useState([]);
useEffect(() => {
const loadIndustries = async () => {
@@ -73,6 +73,7 @@ const CompanyProfile = () => {
industry_id: values.industry,
tax_name: values.taxName,
alamat_lengkap_text: values.alamat_wajib_pajak,
+ street: values.alamat_bisnis,
};
const isUpdated = await odooApi(
'PUT',
@@ -185,17 +186,25 @@ const CompanyProfile = () => {
/>
</div>
<div>
- <label>Nomor NPWP</label>
+ <label>Alamat Wajib Pajak</label>
<input
- {...register('npwp')}
+ {...register('alamat_wajib_pajak')}
type='text'
className='form-input mt-3'
/>
</div>
<div>
- <label>Alamat Wajib Pajak</label>
+ <label>Alamat Bisnis</label>
<input
- {...register('alamat_wajib_pajak')}
+ {...register('alamat_bisnis')}
+ type='text'
+ className='form-input mt-3'
+ />
+ </div>
+ <div>
+ <label>Nomor NPWP</label>
+ <input
+ {...register('npwp')}
type='text'
className='form-input mt-3'
/>
diff --git a/src/lib/checkout/components/Checkout.jsx b/src/lib/checkout/components/Checkout.jsx
index 09a791ee..52f1b3ed 100644
--- a/src/lib/checkout/components/Checkout.jsx
+++ b/src/lib/checkout/components/Checkout.jsx
@@ -77,6 +77,9 @@ const Checkout = () => {
if (!addresses) return;
const matchAddress = (key) => {
+ if (key === 'invoicing') {
+ key = 'invoice';
+ }
const addressToMatch = getItemAddress(key);
const foundAddress = addresses.filter(
(address) => address.id == addressToMatch
diff --git a/src/pages/login.jsx b/src/pages/login.jsx
index 9a1aa85b..07d13784 100644
--- a/src/pages/login.jsx
+++ b/src/pages/login.jsx
@@ -1,3 +1,5 @@
+import { useEffect } from 'react';
+import { useRouter } from 'next/router';
import Seo from '@/core/components/Seo';
import SimpleFooter from '@/core/components/elements/Footer/SimpleFooter';
import BasicLayout from '@/core/components/layouts/BasicLayout';
@@ -5,8 +7,18 @@ import DesktopView from '@/core/components/views/DesktopView';
import MobileView from '@/core/components/views/MobileView';
import LoginComponent from '@/lib/auth/components/Login';
import AccountActivation from '~/modules/account-activation';
+import useAuth from '@/core/hooks/useAuth';
export default function Login() {
+ const router = useRouter();
+ const auth = useAuth();
+
+ useEffect(() => {
+ if (auth) {
+ router.push('/');
+ }
+ }, [auth, router]);
+
return (
<>
<Seo title='Login - Indoteknik.com' />
diff --git a/src/pages/my/address/[id]/edit.jsx b/src/pages/my/address/[id]/edit.jsx
index bd680b90..732ec9fc 100644
--- a/src/pages/my/address/[id]/edit.jsx
+++ b/src/pages/my/address/[id]/edit.jsx
@@ -1,11 +1,11 @@
-import Seo from '@/core/components/Seo'
-import AppLayout from '@/core/components/layouts/AppLayout'
-import BasicLayout from '@/core/components/layouts/BasicLayout'
-import DesktopView from '@/core/components/views/DesktopView'
-import MobileView from '@/core/components/views/MobileView'
-import addressApi from '@/lib/address/api/addressApi'
-import EditAddressComponent from '@/lib/address/components/EditAddress'
-import IsAuth from '@/lib/auth/components/IsAuth'
+import Seo from '@/core/components/Seo';
+import AppLayout from '@/core/components/layouts/AppLayout';
+import BasicLayout from '@/core/components/layouts/BasicLayout';
+import DesktopView from '@/core/components/views/DesktopView';
+import MobileView from '@/core/components/views/MobileView';
+import addressApi from '@/lib/address/api/addressApi';
+import EditAddressComponent from '@/lib/address/components/EditAddress';
+import IsAuth from '@/lib/auth/components/IsAuth';
export default function EditAddress({ id, defaultValues }) {
return (
@@ -24,12 +24,12 @@ export default function EditAddress({ id, defaultValues }) {
</BasicLayout>
</DesktopView>
</IsAuth>
- )
+ );
}
export async function getServerSideProps(context) {
- const { id } = context.query
- const address = await addressApi({ id })
+ const { id } = context.query;
+ const address = await addressApi({ id });
const defaultValues = {
type: address.type,
name: address.name,
@@ -41,7 +41,7 @@ export async function getServerSideProps(context) {
oldDistrict: address.district?.id || '',
district: '',
oldSubDistrict: address.subDistrict?.id || '',
- subDistrict: ''
- }
- return { props: { id, defaultValues } }
+ subDistrict: '',
+ };
+ return { props: { id, defaultValues } };
}
diff --git a/tsconfig.json b/tsconfig.json
index 8613c022..96670169 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,11 +1,7 @@
{
"compilerOptions": {
"target": "ES5",
- "lib": [
- "DOM",
- "DOM.Iterable",
- "ESNext"
- ],
+ "lib": ["DOM", "DOM.Iterable", "ESNext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
@@ -33,10 +29,10 @@
"**/*.ts",
"**/*.tsx",
"**/*.jsx",
- ".next/types/**/*.ts"
-, "src/pages/shop/promo/index.tsx", "src/pages/shop/promo/[slug].jsx" ],
- "exclude": [
- "node_modules",
- "src"
- ]
+ ".next/types/**/*.ts",
+ "src-migrate/**/*",
+ "src/pages/shop/promo/index.tsx",
+ "src/pages/shop/promo/[slug].jsx"
+ ],
+ "exclude": ["node_modules", "src"]
}