207 lines
7.4 KiB
TypeScript
207 lines
7.4 KiB
TypeScript
import { Image } from '@tarojs/components';
|
|
import Taro from '@tarojs/taro';
|
|
|
|
import { forwardRef, useCallback, useEffect, useImperativeHandle, useState } from 'react';
|
|
|
|
import BlFormItem from '@/components/bl-form-item';
|
|
import { BlFormRadio, BlFormRadioGroup } from '@/components/bl-form-radio';
|
|
import BlFormSelect from '@/components/bl-form-select';
|
|
import { EventName, OpenSource, PageUrl } from '@/constants/app';
|
|
import { CITY_CODE_TO_NAME_MAP } from '@/constants/city';
|
|
import { EmployType, EMPLOY_TYPE_TITLE_MAP, FULL_PRICE_OPTIONS, PART_PRICE_OPTIONS } from '@/constants/job';
|
|
import { SalaryRange } from '@/types/job';
|
|
import { MaterialProfile } from '@/types/material';
|
|
import { logWithPrefix } from '@/utils/common';
|
|
import { isFullTimePriceRequired, isPartTimePriceRequired } from '@/utils/job';
|
|
import { getCurrentCityCode } from '@/utils/location';
|
|
import { navigateTo } from '@/utils/route';
|
|
|
|
import './index.less';
|
|
|
|
interface IProps {
|
|
profile: Partial<MaterialProfile>;
|
|
}
|
|
|
|
const PREFIX = 'fragment-profile-intention';
|
|
const log = logWithPrefix(PREFIX);
|
|
const realtimeLogger = Taro.getRealtimeLogManager();
|
|
realtimeLogger.tag(PREFIX);
|
|
const calcInitCityCodes = (codeString: string = '') => {
|
|
const codes = codeString.split('、');
|
|
return codes.filter(code => !!CITY_CODE_TO_NAME_MAP.get(code));
|
|
};
|
|
|
|
const getCityCodeString = (codes: string[]) => {
|
|
return codes.join('、');
|
|
};
|
|
|
|
const calcSalarySelect = (profile: Partial<MaterialProfile>, full: boolean) => {
|
|
const min = full ? profile.fullTimeMinPrice : profile.partyTimeMinPrice;
|
|
const max = full ? profile.fullTimeMaxPrice : profile.partyTimeMaxPrice;
|
|
if (!min || !max) {
|
|
return;
|
|
}
|
|
const options = full ? FULL_PRICE_OPTIONS : PART_PRICE_OPTIONS;
|
|
return options.find(v => v.value && v.value.minSalary <= min && v.value.maxSalary >= max)?.value;
|
|
};
|
|
|
|
const getSalaryPrice = (fullSalary?: SalaryRange, partSalary?: SalaryRange) => {
|
|
const price: Partial<
|
|
Pick<MaterialProfile, 'fullTimeMinPrice' | 'fullTimeMaxPrice' | 'partyTimeMinPrice' | 'partyTimeMaxPrice'>
|
|
> = {};
|
|
if (fullSalary) {
|
|
price.fullTimeMinPrice = fullSalary.minSalary;
|
|
price.fullTimeMaxPrice = fullSalary.maxSalary;
|
|
}
|
|
if (partSalary) {
|
|
price.partyTimeMinPrice = partSalary.minSalary;
|
|
price.partyTimeMaxPrice = partSalary.maxSalary;
|
|
}
|
|
return price;
|
|
};
|
|
|
|
function ProfileIntentionFragment(props: IProps, ref) {
|
|
const { profile } = props;
|
|
const [cityCodes, setCityCodes] = useState(calcInitCityCodes(profile.cityCodes || ''));
|
|
const [employType, setEmployType] = useState(profile.employType);
|
|
const [fullSalary, setFullSalary] = useState(calcSalarySelect(profile, true));
|
|
const [partSalary, setPartSalary] = useState(calcSalarySelect(profile, false));
|
|
const [acceptWorkForSit, setAcceptWorkForSit] = useState(profile.acceptWorkForSit);
|
|
|
|
const handleDeleteCity = useCallback(
|
|
(deleteCode: string) => {
|
|
setCityCodes(cityCodes.filter(code => code !== deleteCode));
|
|
},
|
|
[cityCodes]
|
|
);
|
|
|
|
const handleClickAddCity = useCallback(() => {
|
|
const currentCityCode = getCurrentCityCode();
|
|
realtimeLogger.info('handleClickAddCity', OpenSource.AddIndentCity);
|
|
navigateTo(PageUrl.CitySearchProfile, { city: currentCityCode, source: OpenSource.AddIndentCity });
|
|
}, []);
|
|
|
|
const handleSelectCity = useCallback(
|
|
data => {
|
|
log('handleSelectCity', data);
|
|
realtimeLogger.info('handleSelectCity', data);
|
|
const { openSource, cityCode: code } = data;
|
|
// if (openSource !== OpenSource.AddIndentCity) {
|
|
// return;
|
|
// }
|
|
const newCodes = [...new Set([...cityCodes, code])];
|
|
setCityCodes(newCodes);
|
|
},
|
|
[cityCodes]
|
|
);
|
|
|
|
const handleEmployTypeChange = useCallback((value: EmployType) => {
|
|
setEmployType(value);
|
|
if (value === EmployType.Full) {
|
|
setPartSalary({ minSalary: 0, maxSalary: 0 });
|
|
}
|
|
if (value === EmployType.Part) {
|
|
setFullSalary({ minSalary: 0, maxSalary: 0 });
|
|
}
|
|
}, []);
|
|
|
|
const handleSelectFullSalary = useCallback((value?: SalaryRange) => {
|
|
setFullSalary(value);
|
|
}, []);
|
|
|
|
const handleSelectPartSalary = useCallback((value?: SalaryRange) => {
|
|
setPartSalary(value);
|
|
}, []);
|
|
|
|
const handleAcceptSittingChange = useCallback((value: boolean) => {
|
|
log('handleAcceptSittingChange', value);
|
|
setAcceptWorkForSit(value);
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
Taro.eventCenter.on(EventName.SELECT_CITY, handleSelectCity);
|
|
return () => {
|
|
Taro.eventCenter.off(EventName.SELECT_CITY, handleSelectCity);
|
|
};
|
|
}, [handleSelectCity]);
|
|
|
|
useImperativeHandle(
|
|
ref,
|
|
() => ({
|
|
getData: () => ({
|
|
cityCodes: getCityCodeString(cityCodes),
|
|
employType,
|
|
acceptWorkForSit,
|
|
...getSalaryPrice(fullSalary, partSalary),
|
|
}),
|
|
}),
|
|
[cityCodes, employType, fullSalary, partSalary, acceptWorkForSit]
|
|
);
|
|
|
|
return (
|
|
<div className={PREFIX}>
|
|
<BlFormItem title="意向城市" contentClassName={`${PREFIX}__indent-city-container`} dynamicHeight>
|
|
<div className={`${PREFIX}__indent-city`}>
|
|
{cityCodes.map(code => {
|
|
return (
|
|
<div key={code} className={`${PREFIX}__indent-city__item`}>
|
|
{CITY_CODE_TO_NAME_MAP.get(code)}
|
|
<Image
|
|
mode="aspectFit"
|
|
className={`${PREFIX}__indent-city__delete-icon`}
|
|
src={require('@/statics/svg/circle-delete.svg')}
|
|
onClick={() => handleDeleteCity(code)}
|
|
/>
|
|
</div>
|
|
);
|
|
})}
|
|
{cityCodes.length < 3 && (
|
|
<div className={`${PREFIX}__indent-city__item`} onClick={handleClickAddCity}>
|
|
<Image
|
|
mode="aspectFit"
|
|
className={`${PREFIX}__indent-city__add-icon`}
|
|
src={require('@/statics/svg/add.svg')}
|
|
/>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</BlFormItem>
|
|
<BlFormItem title="工作类型">
|
|
<BlFormRadioGroup direction="horizontal" value={employType} onChange={handleEmployTypeChange}>
|
|
<BlFormRadio name={EmployType.Full} text={EMPLOY_TYPE_TITLE_MAP[EmployType.Full]} value={employType} />
|
|
<BlFormRadio name={EmployType.Part} text={EMPLOY_TYPE_TITLE_MAP[EmployType.Part]} value={employType} />
|
|
<BlFormRadio name={EmployType.All} text={EMPLOY_TYPE_TITLE_MAP[EmployType.All]} value={employType} />
|
|
</BlFormRadioGroup>
|
|
</BlFormItem>
|
|
{isFullTimePriceRequired(employType) && (
|
|
<BlFormItem title="期望全职薪资">
|
|
<BlFormSelect
|
|
title="期望全职薪资"
|
|
value={fullSalary}
|
|
options={FULL_PRICE_OPTIONS}
|
|
onSelect={handleSelectFullSalary}
|
|
/>
|
|
</BlFormItem>
|
|
)}
|
|
{isPartTimePriceRequired(employType) && (
|
|
<BlFormItem title="期望兼职薪资">
|
|
<BlFormSelect
|
|
title="期望兼职薪资"
|
|
value={partSalary}
|
|
options={PART_PRICE_OPTIONS}
|
|
onSelect={handleSelectPartSalary}
|
|
/>
|
|
</BlFormItem>
|
|
)}
|
|
<BlFormItem title="是否接受坐班">
|
|
<BlFormRadioGroup direction="horizontal" value={acceptWorkForSit} onChange={handleAcceptSittingChange}>
|
|
<BlFormRadio name text="接受" value={acceptWorkForSit} />
|
|
<BlFormRadio name={false} text="不接受" value={acceptWorkForSit} />
|
|
</BlFormRadioGroup>
|
|
</BlFormItem>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default forwardRef(ProfileIntentionFragment);
|