upd
This commit is contained in:
@@ -2,6 +2,6 @@ import AboutMain from "@/components/pages/AboutPage/AboutMain";
|
||||
import { InProcess } from "@/components/pages/InProcess";
|
||||
|
||||
export default function AboutPage() {
|
||||
return <InProcess />;
|
||||
// return <AboutMain />;
|
||||
// return <InProcess />;
|
||||
return <AboutMain />;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import { FormProvider, SubmitHandler, useForm } from "react-hook-form";
|
||||
import { ImageUploader } from "../ImageUploader";
|
||||
import { FormModalHeader } from "./FormModalHeader";
|
||||
import CloseIcon from "../icons/CloseIcon";
|
||||
import { ColorPicker } from "@/ui/ColorPicker";
|
||||
|
||||
interface ICompanyFormInput {
|
||||
title: string;
|
||||
@@ -81,7 +82,8 @@ export function CompanyFormModal<TAction extends "create" | "edit">({
|
||||
label="Загрузите или перетащите иконку ( в формате svg )"
|
||||
/>
|
||||
</div>
|
||||
<TextInput name="color" label="Цвет" placeholder="#000000" />
|
||||
{/* <TextInput name="color" label="Цвет" placeholder="#000000" /> */}
|
||||
<ColorPicker name="color" label="Цвет" />
|
||||
</FormProvider>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -11,6 +11,7 @@ import { TextInput } from "@/ui/TextInput";
|
||||
import { DatePicker } from "@/ui/DatePicker";
|
||||
import CloseIcon from "../icons/CloseIcon";
|
||||
import { useModalStore } from "@/stores/useModalStore";
|
||||
import { ColorPicker } from "@/ui/ColorPicker";
|
||||
|
||||
export interface IEventFormInput {
|
||||
dates: string[]; // Изменили с Date[] на string[] для корректной сериализации
|
||||
@@ -76,7 +77,8 @@ function EventFormModal<TAction extends "create" | "edit">({
|
||||
required
|
||||
/>
|
||||
<TextInput name="location" label="Место" placeholder="" />
|
||||
<TextInput name="color" label="Цвет" placeholder="" />
|
||||
{/* <TextInput name="color" label="Цвет" placeholder="" /> */}
|
||||
<ColorPicker name="color" label="Цвет" />
|
||||
</form>
|
||||
</FormProvider>
|
||||
</div>
|
||||
|
||||
@@ -46,14 +46,14 @@ export default function AboutEventCard({
|
||||
style={{ backgroundColor: color }}
|
||||
className="size-2.5 rounded-full mr-2"
|
||||
/>
|
||||
<span>{location}</span>
|
||||
<span className="font-medium">{location}</span>
|
||||
</div>
|
||||
<div
|
||||
className="py-2.5 px-[0.833vw] rounded-[1.111vw] border border-[#FFFFFF1A]
|
||||
max-lg:w-max md:max-lg:py-[1.432vw] md:max-lg:px-[2.604vw] md:max-lg:rounded-full
|
||||
max-md:rounded-[4.444vw] max-md:px-[3.333vw] max-md:py-[1.333vw]"
|
||||
>
|
||||
<span>
|
||||
<span className="font-medium">
|
||||
{dates
|
||||
.map((date) => format(date, "d MMMM", { locale: ru }))
|
||||
.join(" – ")}
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
import { ChangeEvent, useEffect, useRef, useState } from "react";
|
||||
import {
|
||||
FieldValues,
|
||||
Path,
|
||||
PathValue,
|
||||
useFormContext,
|
||||
useWatch,
|
||||
} from "react-hook-form";
|
||||
|
||||
export function ColorPicker<TFieldValues extends FieldValues>({
|
||||
label,
|
||||
name,
|
||||
required = false,
|
||||
}: {
|
||||
label?: string;
|
||||
name: Path<TFieldValues>;
|
||||
required?: boolean;
|
||||
}) {
|
||||
const { register, setValue, control } = useFormContext<TFieldValues>();
|
||||
const [hexValue, setHexValue] = useState("");
|
||||
const isUpdatingRef = useRef(false);
|
||||
|
||||
const currentValue = useWatch({ control, name });
|
||||
|
||||
// Синхронизируем hex input с текущим значением формы
|
||||
useEffect(() => {
|
||||
if (isUpdatingRef.current) return;
|
||||
|
||||
if (currentValue) {
|
||||
const cleanValue = currentValue.replace("#", "");
|
||||
setHexValue(cleanValue);
|
||||
} else {
|
||||
setHexValue("");
|
||||
}
|
||||
}, [currentValue]);
|
||||
|
||||
// Валидация и форматирование hex кода
|
||||
const handleHexChange = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
let value = e.target.value.replace(/[^0-9A-Fa-f]/g, "").toUpperCase();
|
||||
|
||||
// Ограничиваем до 6 символов
|
||||
if (value.length > 6) {
|
||||
value = value.slice(0, 6);
|
||||
}
|
||||
|
||||
setHexValue(value);
|
||||
|
||||
// Устанавливаем флаг обновления
|
||||
isUpdatingRef.current = true;
|
||||
|
||||
// Обновляем значение формы
|
||||
if (value.length === 6) {
|
||||
setValue(name, `#${value}` as any);
|
||||
} else if (value.length === 0) {
|
||||
setValue(name, "" as any);
|
||||
}
|
||||
|
||||
// Сбрасываем флаг после небольшой задержки
|
||||
setTimeout(() => {
|
||||
isUpdatingRef.current = false;
|
||||
}, 0);
|
||||
};
|
||||
|
||||
// Обработка изменения color picker
|
||||
const handleColorChange = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
const colorValue = e.target.value;
|
||||
|
||||
// Устанавливаем флаг обновления
|
||||
isUpdatingRef.current = true;
|
||||
|
||||
setValue(name, colorValue as PathValue<TFieldValues, Path<TFieldValues>>);
|
||||
setHexValue(colorValue.replace("#", ""));
|
||||
|
||||
// Сбрасываем флаг после небольшой задержки
|
||||
setTimeout(() => {
|
||||
isUpdatingRef.current = false;
|
||||
}, 0);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-4 w-full">
|
||||
{label && (
|
||||
<label htmlFor={name + "_" + label} className="heading2 font-medium">
|
||||
{label}
|
||||
</label>
|
||||
)}
|
||||
<div className="flex gap-3 items-end">
|
||||
{/* Color Picker */}
|
||||
<div className="relative flex-shrink-0">
|
||||
<input
|
||||
type="color"
|
||||
className="w-12 h-12 border border-[#37393B] rounded-lg bg-transparent cursor-pointer appearance-none"
|
||||
id={name + "_" + label}
|
||||
value={currentValue || "#000000"}
|
||||
onChange={handleColorChange}
|
||||
style={{
|
||||
WebkitAppearance: "none",
|
||||
MozAppearance: "none",
|
||||
appearance: "none",
|
||||
}}
|
||||
/>
|
||||
<style jsx>{`
|
||||
input[type="color"]::-webkit-color-swatch-wrapper {
|
||||
padding: 0;
|
||||
border-radius: 0.5rem;
|
||||
border: none;
|
||||
}
|
||||
input[type="color"]::-webkit-color-swatch {
|
||||
border: none;
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
input[type="color"]::-moz-color-swatch {
|
||||
border: none;
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
|
||||
{/* Hex Input */}
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center border-b border-[#37393B] pb-1">
|
||||
<span className="text-[#7A7A7A] font-medium btnl mr-1">#</span>
|
||||
<input
|
||||
type="text"
|
||||
className="flex-1 bg-transparent outline-none btnl font-medium text-white placeholder:text-[#7A7A7A] uppercase"
|
||||
placeholder="000000"
|
||||
value={hexValue}
|
||||
onChange={handleHexChange}
|
||||
maxLength={6}
|
||||
/>
|
||||
</div>
|
||||
{hexValue.length > 0 && hexValue.length < 6 && (
|
||||
<p className="text-xs text-[#7A7A7A] mt-1">
|
||||
Введите 6-значный hex код
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Скрытый input для формы */}
|
||||
<input
|
||||
type="hidden"
|
||||
{...register(name, { required })}
|
||||
value={currentValue || ""}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user