Files
myeasycms-v2/packages/ui/src/makerkit/image-uploader.tsx
giancarlo 99db8f4ca4 Implement custom roles and improve permissions logic
The commit refactors the handling of account roles and enhances permissions checks. The account role has been shifted to use a string type, providing the ability to define custom roles. It also introduces the RolesDataProvider component, which stipulates role-related data for different forms and tables. The modification goes further to consider user role hierarchy in permissions checks, offering a more granular access control.
2024-03-29 14:48:45 +08:00

110 lines
2.5 KiB
TypeScript

'use client';
import { useCallback, useEffect, useState } from 'react';
import Image from 'next/image';
import { Image as ImageIcon } from 'lucide-react';
import { useForm } from 'react-hook-form';
import { Button } from '../shadcn/button';
import { ImageUploadInput } from './image-upload-input';
import { Trans } from './trans';
export function ImageUploader(
props: React.PropsWithChildren<{
value: string | null | undefined;
onValueChange: (value: File | null) => unknown;
}>,
) {
const [image, setImage] = useState(props.value);
const { setValue, register } = useForm<{
value: string | null | FileList;
}>({
defaultValues: {
value: props.value,
},
mode: 'onChange',
reValidateMode: 'onChange',
});
const control = register('value');
const onClear = useCallback(() => {
props.onValueChange(null);
setValue('value', null);
setImage('');
}, [props, setValue]);
const onValueChange = useCallback(
({ image, file }: { image: string; file: File }) => {
props.onValueChange(file);
setImage(image);
},
[props],
);
const Input = () => (
<ImageUploadInput
{...control}
accept={'image/*'}
className={'absolute h-full w-full'}
visible={false}
multiple={false}
onValueChange={onValueChange}
/>
);
useEffect(() => {
setImage(props.value);
}, [props.value]);
if (!image) {
return (
<FallbackImage descriptionSection={props.children}>
<Input />
</FallbackImage>
);
}
return (
<div className={'flex items-center space-x-4'}>
<label className={'relative h-20 w-20 animate-in fade-in zoom-in-50'}>
<Image fill className={'h-20 w-20 rounded-full'} src={image} alt={''} />
<Input />
</label>
<div>
<Button onClick={onClear} size={'sm'} variant={'ghost'}>
<Trans i18nKey={'common:clear'} />
</Button>
</div>
</div>
);
}
function FallbackImage(
props: React.PropsWithChildren<{
descriptionSection?: React.ReactNode;
}>,
) {
return (
<div className={'flex items-center space-x-4'}>
<label
className={
'relative flex h-20 w-20 cursor-pointer flex-col items-center justify-center rounded-full border border-border animate-in fade-in zoom-in-50 hover:border-primary'
}
>
<ImageIcon className={'h-8 text-primary'} />
{props.children}
</label>
{props.descriptionSection}
</div>
);
}