288 lines
9.4 KiB
TypeScript
288 lines
9.4 KiB
TypeScript
import React, { RefObject } from 'react';
|
|
import {
|
|
List,
|
|
DatePicker,
|
|
Tag,
|
|
Button,
|
|
Input,
|
|
Radio,
|
|
Space,
|
|
} from 'antd-mobile';
|
|
import ExtraFileCommit from '../../extraFile/commit';
|
|
import dayjs from 'dayjs';
|
|
import { WebComponentProps } from 'oak-frontend-base';
|
|
import { EntityDict } from '../../../oak-app-domain';
|
|
import OakAvatar from '../../../components/extraFile/avatar';
|
|
import Style from './mobile.module.less';
|
|
|
|
|
|
type DataProps = {
|
|
visible: boolean;
|
|
nickname: string;
|
|
name: string;
|
|
birth: string;
|
|
gender: string;
|
|
mobile: string;
|
|
genderOptions: Array<{ label: string; value: 'male' | 'female' }>;
|
|
attrs: Record<string, string>;
|
|
id: string;
|
|
refreshing: boolean;
|
|
canSyncWechat: boolean;
|
|
appId: string;
|
|
editAttr: string;
|
|
executable: boolean | Error;
|
|
nnDirty: boolean;
|
|
nameDirty: boolean;
|
|
birthDirty: boolean;
|
|
genderDirty: boolean;
|
|
|
|
userStateStr: string;
|
|
userStateColor: string;
|
|
idStateStr: string;
|
|
idStateColor: string;
|
|
idState: EntityDict['user']['Schema']['idState'];
|
|
isCreation: boolean;
|
|
authenticateUrl: string;
|
|
changeMobileUrl: string,
|
|
changePasswordUrl: string,
|
|
|
|
|
|
editable: boolean;
|
|
};
|
|
|
|
type MethodsProps = {
|
|
editMobile: () => void;
|
|
editPassword: () => void;
|
|
goAuthenticate: () => void;
|
|
setAvatar: () => void;
|
|
refreshWechatPublicUserInfo: () => void;
|
|
editNickname: () => void;
|
|
editName: () => void;
|
|
editGender: () => void;
|
|
cancelEdit: () => void;
|
|
editBirth: () => void;
|
|
};
|
|
|
|
export default function render(
|
|
props: WebComponentProps<EntityDict, 'user', false, DataProps, MethodsProps>
|
|
) {
|
|
const { data, methods } = props;
|
|
const {
|
|
t,
|
|
clean,
|
|
editMobile,
|
|
goAuthenticate,
|
|
refreshWechatPublicUserInfo,
|
|
editPassword,
|
|
editNickname,
|
|
editName,
|
|
editGender,
|
|
cancelEdit,
|
|
update,
|
|
editBirth,
|
|
execute,
|
|
} = methods;
|
|
const {
|
|
oakFullpath,
|
|
executable,
|
|
nickname,
|
|
name,
|
|
birth,
|
|
gender,
|
|
mobile,
|
|
isCreation,
|
|
id,
|
|
canSyncWechat,
|
|
refreshing,
|
|
editAttr,
|
|
genderOptions,
|
|
oakDirty,
|
|
nnDirty,
|
|
birthDirty,
|
|
nameDirty,
|
|
genderDirty,
|
|
userStateColor,
|
|
userStateStr,
|
|
idStateColor,
|
|
idStateStr,
|
|
idState,
|
|
editable,
|
|
changeMobileUrl,
|
|
changePasswordUrl,
|
|
authenticateUrl,
|
|
} = data;
|
|
|
|
return (
|
|
<div className={Style.container}>
|
|
<div
|
|
className={Style['avatar_container']}
|
|
>
|
|
<OakAvatar
|
|
oakAutoUnmount={true}
|
|
oakPath={oakFullpath + '.extraFile$entity'}
|
|
entity="user"
|
|
entityId={id}
|
|
autoUpload={true}
|
|
/>
|
|
</div>
|
|
<List className={Style.list}>
|
|
<List.Item
|
|
extra={editAttr !== 'nickname' ? (
|
|
<div className={nnDirty ? Style.dirty : undefined}>
|
|
{nickname ? nickname : t('unset')}
|
|
</div>
|
|
) : (
|
|
<Input
|
|
disabled={!editable}
|
|
placeholder={t('placeholder.nickname')}
|
|
autoFocus
|
|
value={nickname}
|
|
onChange={(value) => update({
|
|
nickname: value,
|
|
})}
|
|
onBlur={() => cancelEdit()}
|
|
onEnterPress={() => cancelEdit()}
|
|
/>
|
|
)}
|
|
onClick={editAttr === 'nickname' ? undefined : () => editNickname()}
|
|
>
|
|
{t('user:attr.nickname')}
|
|
</List.Item>
|
|
<List.Item
|
|
extra={editAttr !== 'name' ? (
|
|
<div className={nameDirty ? Style.dirty : undefined}>
|
|
{name ? name : t('unset')}
|
|
</div>
|
|
) : (
|
|
<Input
|
|
disabled={!editable}
|
|
placeholder={t('placeholder.name')}
|
|
autoFocus
|
|
value={name}
|
|
onChange={(value) => update({
|
|
name: value,
|
|
})}
|
|
onBlur={() => cancelEdit()}
|
|
onEnterPress={() => cancelEdit()}
|
|
/>
|
|
)}
|
|
onClick={editAttr === 'name' ? undefined : () => editName()}
|
|
clickable={editable && idState !== 'verified'}
|
|
>
|
|
{t('user:attr.name')}
|
|
</List.Item>
|
|
<List.Item
|
|
extra={editAttr !== 'gender' ? (
|
|
<div className={genderDirty ? Style.dirty : undefined}>
|
|
{gender ? t(`user:v.gender.${gender}`) : t('unset')}
|
|
</div>
|
|
) : (
|
|
<Radio.Group
|
|
disabled={!editable}
|
|
value={gender}
|
|
onChange={(value) => {
|
|
update({
|
|
gender: value as 'male',
|
|
});
|
|
cancelEdit();
|
|
}}
|
|
>
|
|
<Space
|
|
direction="horizontal"
|
|
>
|
|
{genderOptions.map(
|
|
(ele: { value: string; label: string }) => (
|
|
<Radio key={ele.value} value={ele.value}>
|
|
{ele.label}
|
|
</Radio>
|
|
)
|
|
)}
|
|
</Space>
|
|
</Radio.Group>
|
|
)}
|
|
onClick={editAttr === 'gender' ? undefined : () => editGender()}
|
|
clickable={editable && idState !== 'verified'}
|
|
>
|
|
{t('user:attr.gender')}
|
|
</List.Item>
|
|
<List.Item
|
|
extra={
|
|
<div className={birthDirty ? Style.dirty : undefined}>
|
|
{birth ? dayjs(birth).format('YYYY-MM-DD') : t('unset')}
|
|
</div>
|
|
}
|
|
onClick={editAttr === 'birth' ? undefined : () => editBirth()}
|
|
clickable={editable && idState !== 'verified'}
|
|
>
|
|
{t('user:attr.birth')}
|
|
</List.Item>
|
|
{!isCreation && !changeMobileUrl && <List.Item
|
|
extra={mobile ? mobile : t('unset')}
|
|
onClick={() => {
|
|
editMobile();
|
|
}}
|
|
>
|
|
{t('mobile')}
|
|
</List.Item>}
|
|
{!isCreation && !!changePasswordUrl && <List.Item
|
|
extra={'********'}
|
|
onClick={() => {
|
|
editPassword();
|
|
}}
|
|
>
|
|
{t('password')}
|
|
</List.Item>}
|
|
<List.Item
|
|
extra={
|
|
<Tag fill="outline" color={userStateColor}>
|
|
{userStateStr}
|
|
</Tag>
|
|
}
|
|
>
|
|
{t('user:attr.userState')}
|
|
</List.Item>
|
|
{!isCreation && !authenticateUrl && <List.Item
|
|
extra={
|
|
<Tag fill="outline" color={idStateColor}>
|
|
{idStateStr}
|
|
</Tag>
|
|
}
|
|
onClick={() => goAuthenticate()}
|
|
>
|
|
{t('user:attr.idState')}
|
|
</List.Item>}
|
|
</List>
|
|
<DatePicker
|
|
visible={editAttr === 'birth'}
|
|
onClose={() => cancelEdit()}
|
|
precision='day'
|
|
min={new Date('1900-01-01')}
|
|
max={new Date()}
|
|
value={new Date(birth)}
|
|
onConfirm={(value) => {
|
|
update({
|
|
birth: dayjs(value).startOf('day').valueOf(),
|
|
});
|
|
}}
|
|
/>
|
|
<div className={Style.btnContainer}>
|
|
{!oakDirty && canSyncWechat && editable && <Button
|
|
className={Style.syncWechat}
|
|
block
|
|
onClick={() => refreshWechatPublicUserInfo()}
|
|
>
|
|
{t('syncWeChat')}
|
|
</Button>}
|
|
{executable === true && <ExtraFileCommit
|
|
buttonProps={{
|
|
color: 'primary',
|
|
block: true,
|
|
}}
|
|
oakPath={oakFullpath}
|
|
entity="user"
|
|
/>}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|