Merge remote-tracking branch 'akrom/add-reset-attachment'

This commit is contained in:
Verticool 2025-02-03 11:09:16 +06:00
commit dd62962de8
5 changed files with 139 additions and 106 deletions

View File

@ -1,4 +1,5 @@
import { useHapticFeedback } from "@vkruglikov/react-telegram-web-app"; import { useHapticFeedback } from "@vkruglikov/react-telegram-web-app";
import { Replace } from "~/shared/ui/icons/replace";
import { XMark } from "~/shared/ui/icons/x-mark.tsx"; import { XMark } from "~/shared/ui/icons/x-mark.tsx";
@ -36,8 +37,8 @@ export const CoverButton = ({ src, onClick }: CoverButtonProps) => {
} }
> >
<div /> <div />
<div className={"flex gap-2 text-sm"}>Удалить</div> <div className={"flex gap-2 text-sm"}>Изменить</div>
<XMark /> <Replace />
</button> </button>
</div> </div>
); );

View File

@ -14,6 +14,8 @@ import { useRootStore } from "~/shared/stores/root";
import { Checkbox } from "~/shared/ui/checkbox"; import { Checkbox } from "~/shared/ui/checkbox";
import { AudioPlayer } from "~/shared/ui/audio-player"; import { AudioPlayer } from "~/shared/ui/audio-player";
import { HashtagInput } from "~/shared/ui/hashtag-input"; import { HashtagInput } from "~/shared/ui/hashtag-input";
import { XMark } from "~/shared/ui/icons/x-mark";
import { Replace } from "~/shared/ui/icons/replace";
type DataStepProps = { type DataStepProps = {
nextStep(): void; nextStep(): void;
@ -57,119 +59,140 @@ export const DataStep = ({ nextStep }: DataStepProps) => {
})(); })();
}; };
const handleFileReset = () => {
rootStore.setFile(null);
rootStore.setFileSrc('');
rootStore.setFileType('');
}
return ( return (
<section className={"mt-4 px-4 pb-8"}> <section className={"mt-4 px-4 pb-8"}>
<div className={"mb-[30px] flex flex-col text-sm"}> <div className={"mb-[30px] flex flex-col text-sm"}>
<span className={"ml-4"}>/Заполните информацию о контенте</span> <span className={"ml-4"}>/Заполните информацию о контенте</span>
<div> <div>
1/<span className={"text-[#7B7B7B]"}>5</span> 1/<span className={"text-[#7B7B7B]"}>5</span>
</div>
</div> </div>
</div>
<div className={"flex flex-col gap-[20px]"}> <div className={"flex flex-col gap-[20px]"}>
<FormLabel label={"Название"}> <FormLabel label={"Название"}>
<Input <Input
placeholder={"[ Введите название ]"} placeholder={"[ Введите название ]"}
error={form.formState.errors?.name} error={form.formState.errors?.name}
{...form.register("name")} {...form.register("name")}
/> />
</FormLabel> </FormLabel>
<FormLabel label={"Имя автора/исполнителя"}> <FormLabel label={"Имя автора/исполнителя"}>
<Input <Input
placeholder={"[ введите имя автора/исполнителя ]"} placeholder={"[ введите имя автора/исполнителя ]"}
error={form.formState.errors?.author} error={form.formState.errors?.author}
{...form.register("author")} {...form.register("author")}
/> />
</FormLabel> </FormLabel>
<FormLabel label={"Хэштеги"}> <FormLabel label={"Хэштеги"}>
<HashtagInput /> <HashtagInput />
</FormLabel> </FormLabel>
<FormLabel label={"Файл"}> <FormLabel label={"Файл"}>
{!rootStore.fileSrc && <>
<HiddenFileInput <HiddenFileInput
id={"file"} id={"file"}
shouldProcess={false} shouldProcess={false}
accept={"video/mp4,video/x-m4v,video/*,audio/mp3,audio/*"} accept={"video/mp4,video/x-m4v,video/*,audio/mp3,audio/*"}
onChange={(file) => { onChange={(file) => {
rootStore.setFile(file); rootStore.setFile(file);
rootStore.setFileSrc(URL.createObjectURL(file)); rootStore.setFileSrc(URL.createObjectURL(file));
rootStore.setFileType(file.type); // Save the file type for conditional rendering rootStore.setFileType(file.type); // Save the file type for conditional rendering
}} }}
/> />
{!rootStore.fileSrc && <FileButton htmlFor={"file"} />} <FileButton htmlFor={"file"} />
</>}
{rootStore.fileSrc && ( {rootStore.fileSrc && (
<div <div
className={ className={
"w-full border border-white bg-[#2B2B2B] px-[10px] py-[8px] text-sm" "w-full border border-white bg-[#2B2B2B] px-[10px] py-[8px] text-sm"
} }
> >
{rootStore.fileType?.startsWith("audio") ? ( {rootStore.fileType?.startsWith("audio") ? (
<AudioPlayer src={rootStore.fileSrc} /> <AudioPlayer src={rootStore.fileSrc} />
) : ( ) : (
<ReactPlayer <ReactPlayer
playsinline={true} playsinline={true}
controls={true} controls={true}
width="100%" width="100%"
config={{ file: { attributes: { playsInline: true } } }} config={{ file: { attributes: { playsInline: true } } }}
url={rootStore.fileSrc} url={rootStore.fileSrc}
/> />
)} )}
</div> <button
)} onClick={handleFileReset}
</FormLabel> className={
"flex w-full items-center justify-between gap-1 border border-white px-[10px] py-[8px]"
<div className={"flex flex-col gap-2"}>
<FormLabel
label={"Разрешить обложку"}
labelClassName={"flex"}
formLabelAddon={
<Checkbox
onClick={() => rootStore.setAllowCover(!rootStore.allowCover)}
checked={rootStore.allowCover}
/>
} }
/> >
<div />
<div className={"flex gap-2 text-sm"}>Изменить выбор</div>
<Replace />
</button>
</div>
)}
</FormLabel>
{rootStore.allowCover && ( <div className={"flex flex-col gap-2"}>
<FormLabel label={"Обложка"}> <FormLabel
<HiddenFileInput label={"Разрешить обложку"}
id={"cover"} labelClassName={"flex"}
accept={"image/*"} formLabelAddon={
onChange={(cover) => { <Checkbox
rootStore.setCover(cover); onClick={() => rootStore.setAllowCover(!rootStore.allowCover)}
}} checked={rootStore.allowCover}
/> />
{rootStore.cover ? (
<CoverButton
src={URL.createObjectURL(rootStore.cover)}
onClick={() => {
rootStore.setCover(null);
}}
/>
) : (
<FileButton htmlFor={"cover"} />
)}
</FormLabel>
)}
</div>
</div>
<Button
className={"mt-[30px]"}
onClick={handleSubmit}
includeArrows={true}
label={"Готово"}
disabled={
!form.formState.isValid ||
!rootStore.file ||
(rootStore.allowCover && !rootStore.cover)
} }
/> />
</section>
{rootStore.allowCover && (
<FormLabel label={"Обложка"}>
{rootStore.cover ? (
<CoverButton
src={URL.createObjectURL(rootStore.cover)}
onClick={() => {
rootStore.setCover(null);
}}
/>
) : (
<>
<HiddenFileInput
id={"cover"}
accept={"image/*"}
onChange={(cover) => {
rootStore.setCover(cover);
}}
/>
<FileButton htmlFor={"cover"} />
</>
)}
</FormLabel>
)}
</div>
</div>
<Button
className={"mt-[30px]"}
onClick={handleSubmit}
includeArrows={true}
label={"Готово"}
disabled={
!form.formState.isValid ||
!rootStore.file ||
(rootStore.allowCover && !rootStore.cover)
}
/>
</section>
); );
}; };

View File

@ -21,12 +21,12 @@ export const useUploadFile = () => {
}>("/storage", formData, { }>("/storage", formData, {
headers: { headers: {
"Content-Type": "multipart/form-data", "Content-Type": "multipart/form-data",
Authorization: localStorage.getItem('auth_v1_token') ?? "" Authorization: localStorage.getItem('auth_v1_token') || ""
}, },
onUploadProgress: (progressEvent) => { onUploadProgress: (progressEvent) => {
const percentCompleted = Math.round( const percentCompleted = Math.round(
(progressEvent.loaded * 100) / (progressEvent?.total as number) ?? (progressEvent.loaded * 100) / (progressEvent?.total as number) ||
0, 0,
); );
setUploadProgress(percentCompleted); setUploadProgress(percentCompleted);

View File

@ -13,7 +13,7 @@ type RootStore = {
setAuthor: (author: string) => void; setAuthor: (author: string) => void;
file: File | null; file: File | null;
setFile: (file: File) => void; setFile: (file: File | null) => void;
fileType: string; fileType: string;
setFileType: (type: string) => void; setFileType: (type: string) => void;

View File

@ -0,0 +1,9 @@
export const Replace = () => {
return (
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<g opacity="1">
<path d="M15.75 6.01C15.9293 6.01 16.0939 6.07292 16.2229 6.17788C17.3108 7.09184 18.0024 8.46516 18.0024 10C18.0024 12.6888 15.8801 14.8818 13.2193 14.9954L13.0024 15H8.56057L9.78032 16.2197C10.0466 16.4859 10.0708 16.9026 9.85294 17.1962L9.78032 17.2803C9.51406 17.5466 9.09739 17.5708 8.80378 17.3529L8.71966 17.2803L6.21966 14.7803C5.9534 14.5141 5.92919 14.0974 6.14704 13.8038L6.21966 13.7197L8.71966 11.2197C9.01256 10.9268 9.48743 10.9268 9.78032 11.2197C10.0466 11.4859 10.0708 11.9026 9.85294 12.1962L9.78032 12.2803L8.56057 13.5H13.0024C14.871 13.5 16.3975 12.0357 16.4972 10.192L16.5024 10C16.5024 8.91885 16.0122 7.95219 15.2419 7.31017C15.0935 7.17538 15 6.97861 15 6.76C15 6.34579 15.3358 6.01 15.75 6.01ZM10.2197 2.71967C10.4859 2.4534 10.9026 2.4292 11.1962 2.64705L11.2803 2.71967L13.7803 5.21967L13.8529 5.30379C14.0466 5.56478 14.049 5.92299 13.8601 6.18638L13.7803 6.28033L11.2803 8.78033L11.1962 8.85295C10.9352 9.0466 10.577 9.04899 10.3136 8.86012L10.2197 8.78033L10.147 8.69621C9.9534 8.43522 9.951 8.07701 10.1399 7.81362L10.2197 7.71967L11.4386 6.5H6.99757C5.12901 6.5 3.60245 7.96428 3.50275 9.80796L3.49757 10C3.49757 11.0831 3.98958 12.0514 4.7623 12.6934C4.9085 12.8289 4.99999 13.0238 4.99999 13.24C4.99999 13.6542 4.66421 13.99 4.24999 13.99C4.05871 13.99 3.88415 13.9184 3.75166 13.8005C2.67865 12.8872 1.99757 11.5232 1.99757 10C1.99757 7.31124 4.11988 5.11818 6.78068 5.00462L6.99757 5H11.4386L10.2197 3.78033L10.147 3.69621C9.92919 3.4026 9.9534 2.98594 10.2197 2.71967Z" fill="white" />
</g>
</svg>
);
};