postiz/apps/frontend/src/components/marketplace/seller.tsx

242 lines
7.7 KiB
TypeScript

'use client';
import { Slider } from '@gitroom/react/form/slider';
import { Button } from '@gitroom/react/form/button';
import { tagsList } from '@gitroom/nestjs-libraries/database/prisma/marketplace/tags.list';
import { Options } from '@gitroom/frontend/components/marketplace/buyer';
import { ChangeEvent, FC, useCallback, useEffect, useState } from 'react';
import { useFetch } from '@gitroom/helpers/utils/custom.fetch';
import useSWR from 'swr';
import { Input } from '@gitroom/react/form/input';
import { useDebouncedCallback } from 'use-debounce';
import { OrderList } from '@gitroom/frontend/components/marketplace/order.list';
import { useModals } from '@gitroom/frontend/components/layout/new-modal';
import { Select } from '@gitroom/react/form/select';
import { countries } from '@gitroom/nestjs-libraries/services/stripe.country.list';
import { useT } from '@gitroom/react/translation/get.transation.service.client';
export const AddAccount: FC<{
openBankAccount: (country: string) => void;
}> = (props) => {
const { openBankAccount } = props;
const t = useT();
const [country, setCountry] = useState('');
const [loading, setLoading] = useState(false);
return (
<div className="bg-sixth p-[32px] text-[20px] w-full max-w-[600px] mx-auto flex flex-col gap-[24px] rounded-[4px] border border-customColor6 relative">
{t(
'please_select_your_country_where_your_business_is',
'Please select your country where your business is.'
)}
<br />
<Select
label="Country"
name="country"
disableForm={true}
value={country}
onChange={(e) => setCountry(e.target.value)}
>
<option value="">{t('select_country', '--SELECT COUNTRY--')}</option>
{countries.map((country) => (
<option key={country.value} value={country.value}>
{country.label}
</option>
))}
</Select>
<Button
className="w-full"
disabled={!country}
loading={loading}
type="button"
onClick={() => {
openBankAccount(country);
setLoading(true);
}}
>
{t('connect_bank_account', 'Connect Bank Account')}
</Button>
</div>
);
};
export const Seller = () => {
const fetch = useFetch();
const [loading, setLoading] = useState<boolean>(true);
const [keys, setKeys] = useState<
Array<{
key: string;
id: string;
user: string;
}>
>([]);
const [connectedLoading, setConnectedLoading] = useState(false);
const [state, setState] = useState(true);
const [audience, setAudience] = useState<number>(0);
const modals = useModals();
const accountInformation = useCallback(async () => {
const account = await (
await fetch('/marketplace/account', {
method: 'GET',
})
).json();
setState(account.marketplace);
setAudience(account.audience);
return account;
}, []);
const onChange = useCallback((key: string, state: boolean) => {
fetch('/marketplace/item', {
method: 'POST',
body: JSON.stringify({
key,
state,
}),
});
}, []);
const connectBankAccountLink = useCallback(async (country: string) => {
setConnectedLoading(true);
const { url } = await (
await fetch(`/marketplace/bank?country=${country}`, {
method: 'GET',
})
).json();
window.location.href = url;
}, []);
const loadItems = useCallback(async () => {
const data = await (
await fetch('/marketplace/item', {
method: 'GET',
})
).json();
setKeys(data);
setLoading(false);
}, []);
const changeAudienceBackend = useDebouncedCallback(
useCallback(async (aud: number) => {
fetch('/marketplace/audience', {
method: 'POST',
body: JSON.stringify({
audience: aud,
}),
});
}, []),
500
);
const changeAudience = useCallback((e: ChangeEvent<HTMLInputElement>) => {
const num = String(+e.target.value.replace(/\D/g, '') || 0).slice(0, 8);
setAudience(+num);
changeAudienceBackend(+num);
}, []);
const changeMarketplace = useCallback(
async (value: string) => {
await fetch('/marketplace/active', {
method: 'POST',
body: JSON.stringify({
active: value === 'on',
}),
});
setState(!state);
},
[state]
);
const t = useT();
const { data } = useSWR('/marketplace/account', accountInformation);
const connectBankAccount = useCallback(async () => {
if (!data?.connectedAccount) {
modals.openModal({
size: '100%',
classNames: {
modal: 'bg-transparent text-textColor',
},
withCloseButton: false,
children: <AddAccount openBankAccount={connectBankAccountLink} />,
});
return;
}
connectBankAccountLink('');
}, [data, connectBankAccountLink]);
useEffect(() => {
loadItems();
}, []);
if (loading) {
return <></>;
}
return (
<>
<OrderList type="seller" />
<div className="flex mt-[29px] w-full gap-[26px]">
<div className="w-[328px] flex flex-col gap-[16px]">
<h2 className="text-[20px]">{t('seller_mode', 'Seller Mode')}</h2>
<div className="flex p-[24px] bg-sixth rounded-[4px] border border-customColor6 flex-col items-center gap-[16px]">
<div className="w-[64px] h-[64px] bg-customColor38 rounded-full">
{!!data?.picture?.path && (
<img
className="w-full h-full rounded-full"
src={data?.picture?.path || ''}
alt="avatar"
/>
)}
</div>
<div className="text-[24px]">{data?.fullname || ''}</div>
{data?.connectedAccount && (
<div className="flex gap-[16px] items-center pb-[8px]">
<Slider
fill={true}
value={state ? 'on' : 'off'}
onChange={changeMarketplace}
/>
<div className="text-[18px]">{t('active', 'Active')}</div>
</div>
)}
<div className="border-t border-t-customColor43 w-full" />
<div className="w-full">
<Button
className="w-full"
onClick={connectBankAccount}
loading={connectedLoading}
>
{!data?.connectedAccount
? 'Connect Bank Account'
: 'Update Bank Account'}
</Button>
</div>
</div>
</div>
<div className="flex-1 flex gap-[16px] flex-col">
<h2 className="text-[20px]">{t('details', 'Details')}</h2>
<div className="bg-sixth rounded-[4px] border border-customColor6">
{tagsList.map((tag) => (
<Options
rows={3}
key={tag.key}
onChange={onChange}
preSelected={keys.map((key) => key.key)}
search={false}
options={tag.options}
title={tag.name}
/>
))}
<div className="h-[56px] text-[20px] font-[600] flex items-center px-[24px] bg-customColor8">
{t('audience_size', 'Audience Size')}
</div>
<div className="bg-customColor3 flex px-[32px] py-[24px]">
<div className="flex-1">
<Input
label="Audience size on all platforms"
name="audience"
type="text"
pattern="\d*"
max={8}
disableForm={true}
value={audience}
onChange={changeAudience}
/>
</div>
</div>
</div>
</div>
</div>
</>
);
};