mirror of
https://github.com/kmc7468/arkvault.git
synced 2025-12-12 21:08:46 +00:00
카테고리에 파일을 추가할 수 있는 BottomSheet 구현 (WiP)
This commit is contained in:
@@ -42,7 +42,7 @@
|
||||
"prettier": "^3.4.2",
|
||||
"prettier-plugin-svelte": "^3.3.2",
|
||||
"prettier-plugin-tailwindcss": "^0.6.9",
|
||||
"svelte": "^5.17.1",
|
||||
"svelte": "^5.19.1",
|
||||
"svelte-check": "^4.1.3",
|
||||
"tailwindcss": "^3.4.17",
|
||||
"typescript": "^5.7.3",
|
||||
|
||||
82
pnpm-lock.yaml
generated
82
pnpm-lock.yaml
generated
@@ -41,13 +41,13 @@ importers:
|
||||
version: 1.2.12
|
||||
'@sveltejs/adapter-node':
|
||||
specifier: ^5.2.11
|
||||
version: 5.2.11(@sveltejs/kit@2.15.2(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.17.1)(vite@5.4.11(@types/node@22.10.5)))(svelte@5.17.1)(vite@5.4.11(@types/node@22.10.5)))
|
||||
version: 5.2.11(@sveltejs/kit@2.15.2(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.1)(vite@5.4.11(@types/node@22.10.5)))(svelte@5.19.1)(vite@5.4.11(@types/node@22.10.5)))
|
||||
'@sveltejs/kit':
|
||||
specifier: ^2.15.2
|
||||
version: 2.15.2(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.17.1)(vite@5.4.11(@types/node@22.10.5)))(svelte@5.17.1)(vite@5.4.11(@types/node@22.10.5))
|
||||
version: 2.15.2(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.1)(vite@5.4.11(@types/node@22.10.5)))(svelte@5.19.1)(vite@5.4.11(@types/node@22.10.5))
|
||||
'@sveltejs/vite-plugin-svelte':
|
||||
specifier: ^4.0.4
|
||||
version: 4.0.4(svelte@5.17.1)(vite@5.4.11(@types/node@22.10.5))
|
||||
version: 4.0.4(svelte@5.19.1)(vite@5.4.11(@types/node@22.10.5))
|
||||
'@types/file-saver':
|
||||
specifier: ^2.0.7
|
||||
version: 2.0.7
|
||||
@@ -77,7 +77,7 @@ importers:
|
||||
version: 9.1.0(eslint@9.17.0(jiti@2.4.2))
|
||||
eslint-plugin-svelte:
|
||||
specifier: ^2.46.1
|
||||
version: 2.46.1(eslint@9.17.0(jiti@2.4.2))(svelte@5.17.1)
|
||||
version: 2.46.1(eslint@9.17.0(jiti@2.4.2))(svelte@5.19.1)
|
||||
eslint-plugin-tailwindcss:
|
||||
specifier: ^3.17.5
|
||||
version: 3.17.5(tailwindcss@3.4.17)
|
||||
@@ -107,16 +107,16 @@ importers:
|
||||
version: 3.4.2
|
||||
prettier-plugin-svelte:
|
||||
specifier: ^3.3.2
|
||||
version: 3.3.2(prettier@3.4.2)(svelte@5.17.1)
|
||||
version: 3.3.2(prettier@3.4.2)(svelte@5.19.1)
|
||||
prettier-plugin-tailwindcss:
|
||||
specifier: ^0.6.9
|
||||
version: 0.6.9(prettier-plugin-svelte@3.3.2(prettier@3.4.2)(svelte@5.17.1))(prettier@3.4.2)
|
||||
version: 0.6.9(prettier-plugin-svelte@3.3.2(prettier@3.4.2)(svelte@5.19.1))(prettier@3.4.2)
|
||||
svelte:
|
||||
specifier: ^5.17.1
|
||||
version: 5.17.1
|
||||
specifier: ^5.19.1
|
||||
version: 5.19.1
|
||||
svelte-check:
|
||||
specifier: ^4.1.3
|
||||
version: 4.1.3(picomatch@4.0.2)(svelte@5.17.1)(typescript@5.7.3)
|
||||
version: 4.1.3(picomatch@4.0.2)(svelte@5.19.1)(typescript@5.7.3)
|
||||
tailwindcss:
|
||||
specifier: ^3.4.17
|
||||
version: 3.4.17
|
||||
@@ -128,7 +128,7 @@ importers:
|
||||
version: 8.19.1(eslint@9.17.0(jiti@2.4.2))(typescript@5.7.3)
|
||||
unplugin-icons:
|
||||
specifier: ^0.22.0
|
||||
version: 0.22.0(svelte@5.17.1)
|
||||
version: 0.22.0(svelte@5.19.1)
|
||||
vite:
|
||||
specifier: ^5.4.11
|
||||
version: 5.4.11(@types/node@22.10.5)
|
||||
@@ -1114,8 +1114,8 @@ packages:
|
||||
resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==}
|
||||
engines: {node: '>=0.10'}
|
||||
|
||||
esrap@1.3.2:
|
||||
resolution: {integrity: sha512-C4PXusxYhFT98GjLSmb20k9PREuUdporer50dhzGuJu9IJXktbMddVCMLAERl5dAHyAi73GWWCE4FVHGP1794g==}
|
||||
esrap@1.4.3:
|
||||
resolution: {integrity: sha512-Xddc1RsoFJ4z9nR7W7BFaEPIp4UXoeQ0+077UdWLxbafMQFyU79sQJMk7kxNgRwQ9/aVgaKacCHC2pUACGwmYw==}
|
||||
|
||||
esrecurse@4.3.0:
|
||||
resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==}
|
||||
@@ -1992,8 +1992,8 @@ packages:
|
||||
svelte:
|
||||
optional: true
|
||||
|
||||
svelte@5.17.1:
|
||||
resolution: {integrity: sha512-HitqD0XhU9OEytPuux/XYzxle4+7D8+fIb1tHbwMzOtBzDZZO+ESEuwMbahJ/3JoklfmRPB/Gzp74L87Qrxfpw==}
|
||||
svelte@5.19.1:
|
||||
resolution: {integrity: sha512-H/Vs2O51bwILZbaNUSdr4P1NbLpOGsxl4jJAjd88ELjzRgeRi1BHqexcVGannDr7D1pmTYWWajzHOM7bMbtB9Q==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
tailwindcss@3.4.17:
|
||||
@@ -2573,17 +2573,17 @@ snapshots:
|
||||
'@rollup/rollup-win32-x64-msvc@4.30.1':
|
||||
optional: true
|
||||
|
||||
'@sveltejs/adapter-node@5.2.11(@sveltejs/kit@2.15.2(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.17.1)(vite@5.4.11(@types/node@22.10.5)))(svelte@5.17.1)(vite@5.4.11(@types/node@22.10.5)))':
|
||||
'@sveltejs/adapter-node@5.2.11(@sveltejs/kit@2.15.2(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.1)(vite@5.4.11(@types/node@22.10.5)))(svelte@5.19.1)(vite@5.4.11(@types/node@22.10.5)))':
|
||||
dependencies:
|
||||
'@rollup/plugin-commonjs': 28.0.2(rollup@4.30.1)
|
||||
'@rollup/plugin-json': 6.1.0(rollup@4.30.1)
|
||||
'@rollup/plugin-node-resolve': 16.0.0(rollup@4.30.1)
|
||||
'@sveltejs/kit': 2.15.2(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.17.1)(vite@5.4.11(@types/node@22.10.5)))(svelte@5.17.1)(vite@5.4.11(@types/node@22.10.5))
|
||||
'@sveltejs/kit': 2.15.2(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.1)(vite@5.4.11(@types/node@22.10.5)))(svelte@5.19.1)(vite@5.4.11(@types/node@22.10.5))
|
||||
rollup: 4.30.1
|
||||
|
||||
'@sveltejs/kit@2.15.2(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.17.1)(vite@5.4.11(@types/node@22.10.5)))(svelte@5.17.1)(vite@5.4.11(@types/node@22.10.5))':
|
||||
'@sveltejs/kit@2.15.2(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.1)(vite@5.4.11(@types/node@22.10.5)))(svelte@5.19.1)(vite@5.4.11(@types/node@22.10.5))':
|
||||
dependencies:
|
||||
'@sveltejs/vite-plugin-svelte': 4.0.4(svelte@5.17.1)(vite@5.4.11(@types/node@22.10.5))
|
||||
'@sveltejs/vite-plugin-svelte': 4.0.4(svelte@5.19.1)(vite@5.4.11(@types/node@22.10.5))
|
||||
'@types/cookie': 0.6.0
|
||||
cookie: 0.6.0
|
||||
devalue: 5.1.1
|
||||
@@ -2595,27 +2595,27 @@ snapshots:
|
||||
sade: 1.8.1
|
||||
set-cookie-parser: 2.7.1
|
||||
sirv: 3.0.0
|
||||
svelte: 5.17.1
|
||||
svelte: 5.19.1
|
||||
tiny-glob: 0.2.9
|
||||
vite: 5.4.11(@types/node@22.10.5)
|
||||
|
||||
'@sveltejs/vite-plugin-svelte-inspector@3.0.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.17.1)(vite@5.4.11(@types/node@22.10.5)))(svelte@5.17.1)(vite@5.4.11(@types/node@22.10.5))':
|
||||
'@sveltejs/vite-plugin-svelte-inspector@3.0.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.1)(vite@5.4.11(@types/node@22.10.5)))(svelte@5.19.1)(vite@5.4.11(@types/node@22.10.5))':
|
||||
dependencies:
|
||||
'@sveltejs/vite-plugin-svelte': 4.0.4(svelte@5.17.1)(vite@5.4.11(@types/node@22.10.5))
|
||||
'@sveltejs/vite-plugin-svelte': 4.0.4(svelte@5.19.1)(vite@5.4.11(@types/node@22.10.5))
|
||||
debug: 4.4.0
|
||||
svelte: 5.17.1
|
||||
svelte: 5.19.1
|
||||
vite: 5.4.11(@types/node@22.10.5)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.17.1)(vite@5.4.11(@types/node@22.10.5))':
|
||||
'@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.1)(vite@5.4.11(@types/node@22.10.5))':
|
||||
dependencies:
|
||||
'@sveltejs/vite-plugin-svelte-inspector': 3.0.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.17.1)(vite@5.4.11(@types/node@22.10.5)))(svelte@5.17.1)(vite@5.4.11(@types/node@22.10.5))
|
||||
'@sveltejs/vite-plugin-svelte-inspector': 3.0.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.1)(vite@5.4.11(@types/node@22.10.5)))(svelte@5.19.1)(vite@5.4.11(@types/node@22.10.5))
|
||||
debug: 4.4.0
|
||||
deepmerge: 4.3.1
|
||||
kleur: 4.1.5
|
||||
magic-string: 0.30.17
|
||||
svelte: 5.17.1
|
||||
svelte: 5.19.1
|
||||
vite: 5.4.11(@types/node@22.10.5)
|
||||
vitefu: 1.0.5(vite@5.4.11(@types/node@22.10.5))
|
||||
transitivePeerDependencies:
|
||||
@@ -3001,7 +3001,7 @@ snapshots:
|
||||
dependencies:
|
||||
eslint: 9.17.0(jiti@2.4.2)
|
||||
|
||||
eslint-plugin-svelte@2.46.1(eslint@9.17.0(jiti@2.4.2))(svelte@5.17.1):
|
||||
eslint-plugin-svelte@2.46.1(eslint@9.17.0(jiti@2.4.2))(svelte@5.19.1):
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.4.1(eslint@9.17.0(jiti@2.4.2))
|
||||
'@jridgewell/sourcemap-codec': 1.5.0
|
||||
@@ -3014,9 +3014,9 @@ snapshots:
|
||||
postcss-safe-parser: 6.0.0(postcss@8.4.49)
|
||||
postcss-selector-parser: 6.1.2
|
||||
semver: 7.6.3
|
||||
svelte-eslint-parser: 0.43.0(svelte@5.17.1)
|
||||
svelte-eslint-parser: 0.43.0(svelte@5.19.1)
|
||||
optionalDependencies:
|
||||
svelte: 5.17.1
|
||||
svelte: 5.19.1
|
||||
transitivePeerDependencies:
|
||||
- ts-node
|
||||
|
||||
@@ -3099,7 +3099,7 @@ snapshots:
|
||||
dependencies:
|
||||
estraverse: 5.3.0
|
||||
|
||||
esrap@1.3.2:
|
||||
esrap@1.4.3:
|
||||
dependencies:
|
||||
'@jridgewell/sourcemap-codec': 1.5.0
|
||||
|
||||
@@ -3683,16 +3683,16 @@ snapshots:
|
||||
|
||||
prelude-ls@1.2.1: {}
|
||||
|
||||
prettier-plugin-svelte@3.3.2(prettier@3.4.2)(svelte@5.17.1):
|
||||
prettier-plugin-svelte@3.3.2(prettier@3.4.2)(svelte@5.19.1):
|
||||
dependencies:
|
||||
prettier: 3.4.2
|
||||
svelte: 5.17.1
|
||||
svelte: 5.19.1
|
||||
|
||||
prettier-plugin-tailwindcss@0.6.9(prettier-plugin-svelte@3.3.2(prettier@3.4.2)(svelte@5.17.1))(prettier@3.4.2):
|
||||
prettier-plugin-tailwindcss@0.6.9(prettier-plugin-svelte@3.3.2(prettier@3.4.2)(svelte@5.19.1))(prettier@3.4.2):
|
||||
dependencies:
|
||||
prettier: 3.4.2
|
||||
optionalDependencies:
|
||||
prettier-plugin-svelte: 3.3.2(prettier@3.4.2)(svelte@5.17.1)
|
||||
prettier-plugin-svelte: 3.3.2(prettier@3.4.2)(svelte@5.19.1)
|
||||
|
||||
prettier@3.4.2: {}
|
||||
|
||||
@@ -3828,19 +3828,19 @@ snapshots:
|
||||
|
||||
supports-preserve-symlinks-flag@1.0.0: {}
|
||||
|
||||
svelte-check@4.1.3(picomatch@4.0.2)(svelte@5.17.1)(typescript@5.7.3):
|
||||
svelte-check@4.1.3(picomatch@4.0.2)(svelte@5.19.1)(typescript@5.7.3):
|
||||
dependencies:
|
||||
'@jridgewell/trace-mapping': 0.3.25
|
||||
chokidar: 4.0.3
|
||||
fdir: 6.4.2(picomatch@4.0.2)
|
||||
picocolors: 1.1.1
|
||||
sade: 1.8.1
|
||||
svelte: 5.17.1
|
||||
svelte: 5.19.1
|
||||
typescript: 5.7.3
|
||||
transitivePeerDependencies:
|
||||
- picomatch
|
||||
|
||||
svelte-eslint-parser@0.43.0(svelte@5.17.1):
|
||||
svelte-eslint-parser@0.43.0(svelte@5.19.1):
|
||||
dependencies:
|
||||
eslint-scope: 7.2.2
|
||||
eslint-visitor-keys: 3.4.3
|
||||
@@ -3848,9 +3848,9 @@ snapshots:
|
||||
postcss: 8.4.49
|
||||
postcss-scss: 4.0.9(postcss@8.4.49)
|
||||
optionalDependencies:
|
||||
svelte: 5.17.1
|
||||
svelte: 5.19.1
|
||||
|
||||
svelte@5.17.1:
|
||||
svelte@5.19.1:
|
||||
dependencies:
|
||||
'@ampproject/remapping': 2.3.0
|
||||
'@jridgewell/sourcemap-codec': 1.5.0
|
||||
@@ -3861,7 +3861,7 @@ snapshots:
|
||||
axobject-query: 4.1.0
|
||||
clsx: 2.1.1
|
||||
esm-env: 1.2.2
|
||||
esrap: 1.3.2
|
||||
esrap: 1.4.3
|
||||
is-reference: 3.0.3
|
||||
locate-character: 3.0.0
|
||||
magic-string: 0.30.17
|
||||
@@ -3957,7 +3957,7 @@ snapshots:
|
||||
|
||||
undici-types@6.20.0: {}
|
||||
|
||||
unplugin-icons@0.22.0(svelte@5.17.1):
|
||||
unplugin-icons@0.22.0(svelte@5.19.1):
|
||||
dependencies:
|
||||
'@antfu/install-pkg': 0.5.0
|
||||
'@antfu/utils': 0.7.10
|
||||
@@ -3967,7 +3967,7 @@ snapshots:
|
||||
local-pkg: 0.5.1
|
||||
unplugin: 2.1.2
|
||||
optionalDependencies:
|
||||
svelte: 5.17.1
|
||||
svelte: 5.19.1
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
<AdaptiveDiv>
|
||||
<div
|
||||
onclick={(e) => e.stopPropagation()}
|
||||
class="flex max-h-[70vh] min-h-[30vh] rounded-t-2xl bg-white px-4"
|
||||
class="flex max-h-[70vh] min-h-[30vh] overflow-y-auto rounded-t-2xl bg-white px-4"
|
||||
transition:fly={{ y: 100, duration: 200 }}
|
||||
>
|
||||
{@render children?.()}
|
||||
|
||||
19
src/lib/molecules/Categories/Categories.svelte
Normal file
19
src/lib/molecules/Categories/Categories.svelte
Normal file
@@ -0,0 +1,19 @@
|
||||
<script lang="ts">
|
||||
import type { Writable } from "svelte/store";
|
||||
import type { CategoryInfo } from "$lib/modules/filesystem";
|
||||
import Category from "./Category.svelte";
|
||||
import type { SelectedCategory } from "./service";
|
||||
|
||||
interface Props {
|
||||
categories: Writable<CategoryInfo | null>[];
|
||||
onCategoryClick: (category: SelectedCategory) => void;
|
||||
}
|
||||
|
||||
let { categories, onCategoryClick }: Props = $props();
|
||||
</script>
|
||||
|
||||
<div class="space-y-1">
|
||||
{#each categories as category}
|
||||
<Category info={category} onclick={onCategoryClick} />
|
||||
{/each}
|
||||
</div>
|
||||
@@ -1,14 +1,14 @@
|
||||
<script lang="ts">
|
||||
import type { Writable } from "svelte/store";
|
||||
import type { CategoryInfo } from "$lib/modules/filesystem";
|
||||
import type { SelectedSubCategory } from "./service";
|
||||
import type { SelectedCategory } from "./service";
|
||||
|
||||
import IconCategory from "~icons/material-symbols/category";
|
||||
import IconMoreVert from "~icons/material-symbols/more-vert";
|
||||
|
||||
interface Props {
|
||||
info: Writable<CategoryInfo | null>;
|
||||
onclick: (selectedCategory: SelectedSubCategory) => void;
|
||||
onclick: (category: SelectedCategory) => void;
|
||||
}
|
||||
|
||||
let { info, onclick }: Props = $props();
|
||||
2
src/lib/molecules/Categories/index.ts
Normal file
2
src/lib/molecules/Categories/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export { default } from "./Categories.svelte";
|
||||
export * from "./service";
|
||||
6
src/lib/molecules/Categories/service.ts
Normal file
6
src/lib/molecules/Categories/service.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export interface SelectedCategory {
|
||||
id: number;
|
||||
dataKey: CryptoKey;
|
||||
dataKeyVersion: Date;
|
||||
name: string;
|
||||
}
|
||||
57
src/lib/molecules/SubCategories.svelte
Normal file
57
src/lib/molecules/SubCategories.svelte
Normal file
@@ -0,0 +1,57 @@
|
||||
<script lang="ts">
|
||||
import type { ClassValue } from "svelte/elements";
|
||||
import type { Writable } from "svelte/store";
|
||||
import { EntryButton } from "$lib/components/buttons";
|
||||
import { getCategoryInfo, type CategoryInfo } from "$lib/modules/filesystem";
|
||||
import Categories, { type SelectedCategory } from "$lib/molecules/Categories";
|
||||
import { masterKeyStore } from "$lib/stores";
|
||||
|
||||
import IconAddCircle from "~icons/material-symbols/add-circle";
|
||||
|
||||
interface Props {
|
||||
class?: ClassValue;
|
||||
info: CategoryInfo;
|
||||
onSubCategoryClick: (subCategory: SelectedCategory) => void;
|
||||
onSubCategoryCreateClick: () => void;
|
||||
subCategoryCreatePosition?: "top" | "bottom";
|
||||
}
|
||||
|
||||
let {
|
||||
info,
|
||||
onSubCategoryClick,
|
||||
onSubCategoryCreateClick,
|
||||
subCategoryCreatePosition = "bottom",
|
||||
...props
|
||||
}: Props = $props();
|
||||
|
||||
let subCategories: Writable<CategoryInfo | null>[] = $state([]);
|
||||
|
||||
$effect(() => {
|
||||
subCategories = info.subCategoryIds.map((id) =>
|
||||
getCategoryInfo(id, $masterKeyStore?.get(1)?.key!),
|
||||
);
|
||||
|
||||
// TODO: Sorting
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class={["space-y-1", props.class]}>
|
||||
{#snippet subCategoryCreate()}
|
||||
<EntryButton onclick={onSubCategoryCreateClick}>
|
||||
<div class="flex h-8 items-center gap-x-4">
|
||||
<IconAddCircle class="text-lg text-gray-600" />
|
||||
<p class="font-medium text-gray-700">카테고리 추가하기</p>
|
||||
</div>
|
||||
</EntryButton>
|
||||
{/snippet}
|
||||
|
||||
{#if subCategoryCreatePosition === "top"}
|
||||
{@render subCategoryCreate()}
|
||||
{/if}
|
||||
{#key info}
|
||||
<Categories categories={subCategories} onCategoryClick={onSubCategoryClick} />
|
||||
{/key}
|
||||
{#if subCategoryCreatePosition === "bottom"}
|
||||
{@render subCategoryCreate()}
|
||||
{/if}
|
||||
</div>
|
||||
@@ -1,23 +1,21 @@
|
||||
<script lang="ts">
|
||||
import type { Writable } from "svelte/store";
|
||||
import { EntryButton } from "$lib/components/buttons";
|
||||
import {
|
||||
getFileInfo,
|
||||
getCategoryInfo,
|
||||
type FileInfo,
|
||||
type CategoryInfo,
|
||||
} from "$lib/modules/filesystem";
|
||||
import type { SelectedCategory } from "$lib/molecules/Categories";
|
||||
import SubCategories from "$lib/molecules/SubCategories.svelte";
|
||||
import { masterKeyStore } from "$lib/stores";
|
||||
import File from "./File.svelte";
|
||||
import SubCategory from "./SubCategory.svelte";
|
||||
import type { SelectedSubCategory, SelectedFile } from "./service";
|
||||
|
||||
import IconAddCircle from "~icons/material-symbols/add-circle";
|
||||
import type { SelectedFile } from "./service";
|
||||
|
||||
interface Props {
|
||||
info: CategoryInfo;
|
||||
onFileClick: (file: SelectedFile) => void;
|
||||
onSubCategoryClick: (subCategory: SelectedSubCategory) => void;
|
||||
onSubCategoryClick: (subCategory: SelectedCategory) => void;
|
||||
onSubCategoryCreateClick: () => void;
|
||||
}
|
||||
|
||||
@@ -41,19 +39,7 @@
|
||||
{#if info.id !== "root"}
|
||||
<p class="text-lg font-bold text-gray-800">하위 카테고리</p>
|
||||
{/if}
|
||||
<div class="space-y-1">
|
||||
{#key info}
|
||||
{#each subCategories as subCategory}
|
||||
<SubCategory info={subCategory} onclick={onSubCategoryClick} />
|
||||
{/each}
|
||||
{/key}
|
||||
<EntryButton onclick={onSubCategoryCreateClick}>
|
||||
<div class="flex h-8 items-center gap-x-4">
|
||||
<IconAddCircle class="text-lg text-gray-600" />
|
||||
<p class="font-medium text-gray-700">카테고리 추가하기</p>
|
||||
</div>
|
||||
</EntryButton>
|
||||
</div>
|
||||
<SubCategories {info} {onSubCategoryClick} {onSubCategoryCreateClick} />
|
||||
</div>
|
||||
{#if info.id !== "root"}
|
||||
<div class="space-y-4 bg-white p-4">
|
||||
|
||||
@@ -1,10 +1,3 @@
|
||||
export interface SelectedSubCategory {
|
||||
id: number;
|
||||
dataKey: CryptoKey;
|
||||
dataKeyVersion: Date;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface SelectedFile {
|
||||
id: number;
|
||||
dataKey: CryptoKey;
|
||||
|
||||
@@ -5,13 +5,16 @@
|
||||
import { TopBar } from "$lib/components";
|
||||
import { getFileInfo, type FileInfo } from "$lib/modules/filesystem";
|
||||
import { fileDownloadStatusStore, isFileDownloading, masterKeyStore } from "$lib/stores";
|
||||
import AddToCategoryBottomSheet from "./AddToCategoryBottomSheet.svelte";
|
||||
import DownloadStatus from "./DownloadStatus.svelte";
|
||||
import { requestFileDownload } from "./service";
|
||||
import { requestFileDownload, requestFileAdditionToCategory } from "./service";
|
||||
|
||||
let { data } = $props();
|
||||
|
||||
let info: Writable<FileInfo | null> | undefined = $state();
|
||||
|
||||
let isAddToCategoryBottomSheetOpen = $state(true);
|
||||
|
||||
const downloadStatus = $derived(
|
||||
$fileDownloadStatusStore.find((statusStore) => {
|
||||
const { id, status } = get(statusStore);
|
||||
@@ -44,6 +47,11 @@
|
||||
return fileBlob;
|
||||
};
|
||||
|
||||
const addToCategory = async (categoryId: number) => {
|
||||
await requestFileAdditionToCategory(data.id, categoryId);
|
||||
isAddToCategoryBottomSheetOpen = false;
|
||||
};
|
||||
|
||||
$effect(() => {
|
||||
info = getFileInfo(data.id, $masterKeyStore?.get(1)?.key!);
|
||||
isDownloadRequested = false;
|
||||
@@ -105,3 +113,8 @@
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<AddToCategoryBottomSheet
|
||||
bind:isOpen={isAddToCategoryBottomSheetOpen}
|
||||
onAddToCategoryClick={addToCategory}
|
||||
/>
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from "svelte";
|
||||
import type { Writable } from "svelte/store";
|
||||
import { BottomSheet } from "$lib/components";
|
||||
import { Button } from "$lib/components/buttons";
|
||||
import { BottomDiv } from "$lib/components/divs";
|
||||
import { getCategoryInfo, type CategoryInfo } from "$lib/modules/filesystem";
|
||||
import SubCategories from "$lib/molecules/SubCategories.svelte";
|
||||
import { masterKeyStore } from "$lib/stores";
|
||||
|
||||
interface Props {
|
||||
onAddToCategoryClick: (categoryId: number) => void;
|
||||
isOpen: boolean;
|
||||
}
|
||||
|
||||
let { onAddToCategoryClick, isOpen = $bindable() }: Props = $props();
|
||||
|
||||
let category: Writable<CategoryInfo | null> | undefined = $state();
|
||||
|
||||
onMount(() => {
|
||||
category = getCategoryInfo("root", $masterKeyStore?.get(1)?.key!);
|
||||
});
|
||||
</script>
|
||||
|
||||
<BottomSheet bind:isOpen>
|
||||
<div class="flex w-full flex-col justify-between">
|
||||
{#if $category}
|
||||
<SubCategories
|
||||
class="h-fit py-4"
|
||||
info={$category}
|
||||
onSubCategoryClick={({ id }) =>
|
||||
(category = getCategoryInfo(id, $masterKeyStore?.get(1)?.key!))}
|
||||
subCategoryCreatePosition="top"
|
||||
/>
|
||||
{#if $category.id !== "root"}
|
||||
<BottomDiv>
|
||||
<Button onclick={() => onAddToCategoryClick($category.id)}>이 카테고리에 추가하기</Button>
|
||||
</BottomDiv>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
</BottomSheet>
|
||||
@@ -1,4 +1,6 @@
|
||||
import { callPostApi } from "$lib/hooks";
|
||||
import { getFileCache, storeFileCache, downloadFile } from "$lib/modules/file";
|
||||
import type { CategoryFileAddRequest } from "$lib/server/schemas";
|
||||
|
||||
export const requestFileDownload = async (
|
||||
fileId: number,
|
||||
@@ -12,3 +14,10 @@ export const requestFileDownload = async (
|
||||
storeFileCache(fileId, fileBuffer); // Intended
|
||||
return fileBuffer;
|
||||
};
|
||||
|
||||
export const requestFileAdditionToCategory = async (fileId: number, categoryId: number) => {
|
||||
const res = await callPostApi<CategoryFileAddRequest>(`/api/category/${categoryId}/file/add`, {
|
||||
file: fileId,
|
||||
});
|
||||
return res.ok;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user