This commit is contained in:
Louis Knight-Webb
2025-06-17 20:20:48 -04:00
parent 56e8f61064
commit 79a45b141f
2 changed files with 31 additions and 12 deletions

View File

@@ -200,11 +200,10 @@ impl Task {
} }
pub async fn delete(pool: &SqlitePool, id: Uuid, project_id: Uuid) -> Result<u64, sqlx::Error> { pub async fn delete(pool: &SqlitePool, id: Uuid, project_id: Uuid) -> Result<u64, sqlx::Error> {
let project_id_str = project_id.to_string();
let result = sqlx::query!( let result = sqlx::query!(
"DELETE FROM tasks WHERE id = $1 AND project_id = $2", "DELETE FROM tasks WHERE id = $1 AND project_id = $2",
id, id,
project_id_str project_id
) )
.execute(pool) .execute(pool)
.await?; .await?;
@@ -216,12 +215,10 @@ impl Task {
id: Uuid, id: Uuid,
project_id: Uuid, project_id: Uuid,
) -> Result<bool, sqlx::Error> { ) -> Result<bool, sqlx::Error> {
let id_str = id.to_string();
let project_id_str = project_id.to_string();
let result = sqlx::query!( let result = sqlx::query!(
"SELECT id FROM tasks WHERE id = $1 AND project_id = $2", "SELECT id FROM tasks WHERE id = $1 AND project_id = $2",
id_str, id,
project_id_str project_id
) )
.fetch_optional(pool) .fetch_optional(pool)
.await?; .await?;

View File

@@ -1,9 +1,9 @@
import React, { useState, useEffect } from 'react' import React, { useState, useEffect, useMemo } from 'react'
import { Button } from '@/components/ui/button' import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input' import { Input } from '@/components/ui/input'
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog' import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog'
import { Alert, AlertDescription } from '@/components/ui/alert' import { Alert, AlertDescription } from '@/components/ui/alert'
import { Folder, FolderOpen, File, AlertCircle, Home, ChevronUp } from 'lucide-react' import { Folder, FolderOpen, File, AlertCircle, Home, ChevronUp, Search } from 'lucide-react'
import { makeRequest } from '@/lib/api' import { makeRequest } from '@/lib/api'
import { DirectoryEntry } from 'shared/types' import { DirectoryEntry } from 'shared/types'
@@ -29,6 +29,14 @@ export function FolderPicker({
const [loading, setLoading] = useState(false) const [loading, setLoading] = useState(false)
const [error, setError] = useState('') const [error, setError] = useState('')
const [manualPath, setManualPath] = useState(value) const [manualPath, setManualPath] = useState(value)
const [searchTerm, setSearchTerm] = useState('')
const filteredEntries = useMemo(() => {
if (!searchTerm.trim()) return entries
return entries.filter(entry =>
entry.name.toLowerCase().includes(searchTerm.toLowerCase())
)
}, [entries, searchTerm])
useEffect(() => { useEffect(() => {
if (open) { if (open) {
@@ -113,7 +121,7 @@ export function FolderPicker({
return ( return (
<Dialog open={open} onOpenChange={handleClose}> <Dialog open={open} onOpenChange={handleClose}>
<DialogContent className="max-w-[600px] w-full h-[500px] flex flex-col overflow-hidden"> <DialogContent className="max-w-[600px] w-full h-[700px] flex flex-col overflow-hidden">
<DialogHeader> <DialogHeader>
<DialogTitle>{title}</DialogTitle> <DialogTitle>{title}</DialogTitle>
<DialogDescription>{description}</DialogDescription> <DialogDescription>{description}</DialogDescription>
@@ -146,6 +154,20 @@ export function FolderPicker({
</div> </div>
</div> </div>
{/* Search input */}
<div className="space-y-2">
<div className="text-sm font-medium">Search current directory:</div>
<div className="relative">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground" />
<Input
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
placeholder="Filter folders and files..."
className="pl-10"
/>
</div>
</div>
{/* Navigation */} {/* Navigation */}
<div className="flex items-center space-x-2 min-w-0"> <div className="flex items-center space-x-2 min-w-0">
<Button <Button
@@ -190,13 +212,13 @@ export function FolderPicker({
<AlertCircle className="h-4 w-4" /> <AlertCircle className="h-4 w-4" />
<AlertDescription>{error}</AlertDescription> <AlertDescription>{error}</AlertDescription>
</Alert> </Alert>
) : entries.length === 0 ? ( ) : filteredEntries.length === 0 ? (
<div className="p-4 text-center text-muted-foreground"> <div className="p-4 text-center text-muted-foreground">
No folders found {searchTerm.trim() ? 'No matches found' : 'No folders found'}
</div> </div>
) : ( ) : (
<div className="p-2"> <div className="p-2">
{entries.map((entry, index) => ( {filteredEntries.map((entry, index) => (
<div <div
key={index} key={index}
className={`flex items-center space-x-2 p-2 rounded cursor-pointer hover:bg-accent ${ className={`flex items-center space-x-2 p-2 rounded cursor-pointer hover:bg-accent ${