mirror of
https://github.com/linsa-io/linsa.git
synced 2026-01-12 12:20:23 +01:00
.
This commit is contained in:
@@ -6,8 +6,8 @@ import { Button } from "@/components/ui/button"
|
|||||||
import { useAccount } from "@/lib/providers/jazz-provider"
|
import { useAccount } from "@/lib/providers/jazz-provider"
|
||||||
import { LaIcon } from "@/components/custom/la-icon"
|
import { LaIcon } from "@/components/custom/la-icon"
|
||||||
import { Checkbox } from "@/components/ui/checkbox"
|
import { Checkbox } from "@/components/ui/checkbox"
|
||||||
import { format } from "date-fns"
|
|
||||||
import { DatePicker } from "@/components/ui/date-picker"
|
import { DatePicker } from "@/components/ui/date-picker"
|
||||||
|
import { format, parse } from "date-fns"
|
||||||
|
|
||||||
interface TaskFormProps {
|
interface TaskFormProps {
|
||||||
filter?: "today" | "upcoming" | undefined
|
filter?: "today" | "upcoming" | undefined
|
||||||
@@ -19,9 +19,14 @@ export const TaskForm: React.FC<TaskFormProps> = ({ filter }) => {
|
|||||||
const [inputVisible, setInputVisible] = useState(false)
|
const [inputVisible, setInputVisible] = useState(false)
|
||||||
const { me } = useAccount({ root: {} })
|
const { me } = useAccount({ root: {} })
|
||||||
const inputRef = useRef<HTMLInputElement>(null)
|
const inputRef = useRef<HTMLInputElement>(null)
|
||||||
|
const formRef = useRef<HTMLDivElement>(null)
|
||||||
|
|
||||||
const handleSubmit = (e: React.FormEvent) => {
|
const handleSubmit = (e: React.FormEvent) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
saveTask()
|
||||||
|
}
|
||||||
|
|
||||||
|
const saveTask = () => {
|
||||||
if (title.trim() && (filter !== "upcoming" || dueDate)) {
|
if (title.trim() && (filter !== "upcoming" || dueDate)) {
|
||||||
if (me?.root?.tasks === undefined) {
|
if (me?.root?.tasks === undefined) {
|
||||||
if (!me) return
|
if (!me) return
|
||||||
@@ -64,6 +69,23 @@ export const TaskForm: React.FC<TaskFormProps> = ({ filter }) => {
|
|||||||
}
|
}
|
||||||
}, [inputVisible])
|
}, [inputVisible])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const handleClickOutside = (event: MouseEvent) => {
|
||||||
|
if (formRef.current && !formRef.current.contains(event.target as Node)) {
|
||||||
|
if (title.trim()) {
|
||||||
|
saveTask()
|
||||||
|
} else {
|
||||||
|
resetForm()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener("mousedown", handleClickOutside)
|
||||||
|
return () => {
|
||||||
|
document.removeEventListener("mousedown", handleClickOutside)
|
||||||
|
}
|
||||||
|
}, [title, dueDate])
|
||||||
|
|
||||||
const formattedDate = dueDate ? format(dueDate, "EEE, MMMM do, yyyy") : "Select a date"
|
const formattedDate = dueDate ? format(dueDate, "EEE, MMMM do, yyyy") : "Select a date"
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -76,7 +98,7 @@ export const TaskForm: React.FC<TaskFormProps> = ({ filter }) => {
|
|||||||
initial={{ opacity: 0, width: 0 }}
|
initial={{ opacity: 0, width: 0 }}
|
||||||
animate={{ opacity: 1, width: "auto" }}
|
animate={{ opacity: 1, width: "auto" }}
|
||||||
exit={{ opacity: 0, width: 0 }}
|
exit={{ opacity: 0, width: 0 }}
|
||||||
transition={{ duration: 0.3 }}
|
transition={{ duration: 0.01 }}
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
className="flex flex-row items-center gap-1"
|
className="flex flex-row items-center gap-1"
|
||||||
@@ -88,17 +110,13 @@ export const TaskForm: React.FC<TaskFormProps> = ({ filter }) => {
|
|||||||
</Button>
|
</Button>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
) : (
|
) : (
|
||||||
<motion.form
|
<div
|
||||||
key="input-form"
|
ref={formRef}
|
||||||
initial={{ width: 0, opacity: 0 }}
|
|
||||||
animate={{ width: "100%", opacity: 1 }}
|
|
||||||
exit={{ width: 0, opacity: 0 }}
|
|
||||||
transition={{ duration: 0.3 }}
|
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className="bg-result flex w-full items-center justify-between rounded-lg p-2 px-3"
|
className="bg-result flex w-full items-center justify-between rounded-lg px-2 py-1"
|
||||||
>
|
>
|
||||||
<div className="flex flex-row items-center gap-3">
|
<div className="flex min-w-0 flex-1 items-center">
|
||||||
<Checkbox checked={false} onCheckedChange={() => {}} />
|
<Checkbox checked={false} onCheckedChange={() => {}} className="mr-2" />
|
||||||
<Input
|
<Input
|
||||||
autoFocus
|
autoFocus
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
@@ -109,13 +127,17 @@ export const TaskForm: React.FC<TaskFormProps> = ({ filter }) => {
|
|||||||
placeholder="Task title"
|
placeholder="Task title"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center space-x-2">
|
|
||||||
|
<div className="ml-2 flex items-center" onClick={e => e.stopPropagation()}>
|
||||||
{filter === "upcoming" && (
|
{filter === "upcoming" && (
|
||||||
<DatePicker date={dueDate} onDateChange={(date: Date | undefined) => setDueDate(date)} />
|
<DatePicker
|
||||||
|
date={dueDate}
|
||||||
|
onDateChange={(date: Date | undefined) => setDueDate(date)}
|
||||||
|
className="z-50"
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
<span className="text-muted-foreground text-xs">{formattedDate}</span>
|
|
||||||
</div>
|
</div>
|
||||||
</motion.form>
|
</div>
|
||||||
)
|
)
|
||||||
) : null}
|
) : null}
|
||||||
</AnimatePresence>
|
</AnimatePresence>
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export function DatePicker({ date, onDateChange, className }: DatePickerProps) {
|
|||||||
|
|
||||||
const selectDate = (selectedDate: Date | undefined) => {
|
const selectDate = (selectedDate: Date | undefined) => {
|
||||||
onDateChange(selectedDate)
|
onDateChange(selectedDate)
|
||||||
setOpen(false) // Закрываем Popover после выбора даты
|
setOpen(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -26,12 +26,13 @@ export function DatePicker({ date, onDateChange, className }: DatePickerProps) {
|
|||||||
<Button
|
<Button
|
||||||
variant={"outline"}
|
variant={"outline"}
|
||||||
className={cn("w-[240px] justify-start text-left font-normal", !date && "text-muted-foreground", className)}
|
className={cn("w-[240px] justify-start text-left font-normal", !date && "text-muted-foreground", className)}
|
||||||
|
onClick={e => e.stopPropagation()}
|
||||||
>
|
>
|
||||||
<CalendarIcon className="mr-2 h-4 w-4" />
|
<CalendarIcon className="mr-2 h-4 w-4" />
|
||||||
{date ? format(date, "PPP") : <span>Pick a date</span>}
|
{date ? format(date, "PPP") : <span>Pick a date</span>}
|
||||||
</Button>
|
</Button>
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent className="w-auto p-0" align="start">
|
<PopoverContent className="w-auto p-0" align="start" onClick={e => e.stopPropagation()}>
|
||||||
<Calendar mode="single" selected={date} onSelect={selectDate} initialFocus />
|
<Calendar mode="single" selected={date} onSelect={selectDate} initialFocus />
|
||||||
</PopoverContent>
|
</PopoverContent>
|
||||||
</Popover>
|
</Popover>
|
||||||
|
|||||||
Reference in New Issue
Block a user