검색 기능 구현

This commit is contained in:
static
2026-01-15 15:11:03 +09:00
parent 96d5397cb5
commit 37bd6a9315
26 changed files with 757 additions and 35 deletions

View File

@@ -76,7 +76,7 @@
<div class="min-h-full bg-gray-100 pb-[5.5em]">
{#if info?.exists}
<div class="space-y-4">
<div class="space-y-4 bg-white p-4">
<div class="space-y-2 bg-white p-4">
{#if info.id !== "root"}
<p class="text-lg font-bold text-gray-800">하위 카테고리</p>
{/if}
@@ -84,6 +84,7 @@
{info}
onSubCategoryClick={({ id }) => goto(`/category/${id}`)}
onSubCategoryCreateClick={() => (isCategoryCreateModalOpen = true)}
subCategoryCreatePosition="bottom"
onSubCategoryMenuClick={(subCategory) => {
context.selectedCategory = subCategory;
isCategoryMenuBottomSheetOpen = true;
@@ -92,14 +93,19 @@
/>
</div>
{#if info.id !== "root"}
<div class="space-y-4 bg-white p-4">
<div class="space-y-2 bg-white p-4">
<div class="flex items-center justify-between">
<p class="text-lg font-bold text-gray-800">파일</p>
<CheckBox bind:checked={info.isFileRecursive}>
<p class="font-medium">하위 카테고리의 파일</p>
</CheckBox>
</div>
<RowVirtualizer count={files.length} itemHeight={() => 48} itemGap={4}>
<RowVirtualizer
count={files.length}
getItemKey={(index) => files[index]!.details.id}
estimateItemHeight={() => 48}
itemGap={4}
>
{#snippet item(index)}
{@const { details } = files[index]!}
<File

View File

@@ -25,6 +25,7 @@
requestEntryDeletion,
} from "./service.svelte";
import IconSearch from "~icons/material-symbols/search";
import IconAdd from "~icons/material-symbols/add";
let { data } = $props();
@@ -43,8 +44,19 @@
let isEntryRenameModalOpen = $state(false);
let isEntryDeleteModalOpen = $state(false);
let isFromFilePage = $derived(page.url.searchParams.get("from") === "file");
let showTopBar = $derived(data.id !== "root" || isFromFilePage);
let showParentEntry = $derived(
["file", "search"].includes(page.url.searchParams.get("from") ?? ""),
);
let showBackButton = $derived(data.id !== "root" || showParentEntry);
const onSearchClick = async () => {
const params = new URLSearchParams();
if (data.id !== "root") {
params.set("directoryId", data.id.toString());
}
const query = params.toString();
await goto(`/search${query ? `?${query}` : ""}`);
};
const uploadFile = () => {
const files = fileInput?.files;
@@ -96,11 +108,16 @@
<input bind:this={fileInput} onchange={uploadFile} type="file" multiple class="hidden" />
<div class="flex h-full flex-col">
{#if showTopBar}
<TopBar title={info?.name} class="flex-shrink-0" />
{/if}
<TopBar title={info?.name ?? "내 파일"} {showBackButton} class="flex-shrink-0">
<button
onclick={onSearchClick}
class="w-[2.3rem] flex-shrink-0 rounded-full p-1 active:bg-black active:bg-opacity-[0.04]"
>
<IconSearch class="text-2xl" />
</button>
</TopBar>
{#if info?.exists}
<div class={["flex flex-grow flex-col px-4 pb-4", !showTopBar && "pt-4"]}>
<div class="flex flex-grow flex-col px-4 pb-4">
<div class="flex gap-x-2">
<UploadStatusCard onclick={() => goto("/file/uploads")} />
<DownloadStatusCard onclick={() => goto("/file/downloads")} />
@@ -113,12 +130,12 @@
context.selectedEntry = entry;
isEntryMenuBottomSheetOpen = true;
}}
showParentEntry={isFromFilePage && info.parentId !== undefined}
showParentEntry={showParentEntry && data.id !== "root"}
onParentClick={() =>
goto(
info!.parentId === "root"
? "/directory?from=file"
: `/directory/${info!.parentId}?from=file`,
? `/directory?from=${page.url.searchParams.get("from")}`
: `/directory/${info!.parentId}?from=${page.url.searchParams.get("from")}`,
)}
/>
{/key}

View File

@@ -46,7 +46,16 @@
</script>
{#if entries.length > 0}
<RowVirtualizer count={entries.length} itemHeight={() => 56} itemGap={4} class="pb-[4.5rem]">
<RowVirtualizer
count={entries.length}
getItemKey={(index) =>
entries[index]!.type !== "parent"
? `${entries[index]!.type}-${entries[index]!.details.id}`
: entries[index]!.type!}
estimateItemHeight={() => 56}
itemGap={4}
class="pb-[4.5rem]"
>
{#snippet item(index)}
{@const entry = entries[index]!}
{#if entry.type === "parent"}