Skip to content

Commit 60c551a

Browse files
aster-voidclaude
andcommitted
modules/site: add member search to public search
- Add member variant to SearchResult type - Include searchMembers() in searchPublic query - Handle member results in site-search-modal (icon, label, href) - Add member results section to search page 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
1 parent c7ae749 commit 60c551a

File tree

4 files changed

+62
-10
lines changed

4 files changed

+62
-10
lines changed

src/lib/components/site-search-modal.svelte

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
</script>
44

55
<script lang="ts">
6-
import { FileText, Folder } from "lucide-svelte";
6+
import { FileText, Folder, User } from "lucide-svelte";
77
import { searchPublic } from "$lib/data/public/index.remote";
88
import type { SearchResult } from "$lib/shared/logic/search";
99
import SearchModalBase from "./search-modal-base.svelte";
@@ -14,6 +14,8 @@
1414
return FileText;
1515
case "project":
1616
return Folder;
17+
case "member":
18+
return User;
1719
}
1820
}
1921
@@ -23,6 +25,8 @@
2325
return "Article";
2426
case "project":
2527
return "Project";
28+
case "member":
29+
return "Member";
2630
}
2731
}
2832
@@ -32,6 +36,8 @@
3236
return result.title;
3337
case "project":
3438
return result.name;
39+
case "member":
40+
return result.name;
3541
}
3642
}
3743
@@ -41,6 +47,8 @@
4147
return `/articles/${result.slug}`;
4248
case "project":
4349
return `/projects/${result.slug}`;
50+
case "member":
51+
return `/members/${result.slug}`;
4452
}
4553
}
4654
@@ -52,8 +60,11 @@
5260
parts.push(result.publishedAt.toLocaleDateString("ja-JP"));
5361
}
5462
return parts.join(" · ");
63+
} else if (result.type === "project") {
64+
return result.description ?? "";
65+
} else {
66+
return result.bio ?? "";
5567
}
56-
return result.description ?? "";
5768
}
5869
</script>
5970

@@ -63,7 +74,7 @@
6374
{getResultIcon}
6475
{getResultName}
6576
{getResultHref}
66-
placeholder="記事やプロジェクトを検索..."
77+
placeholder="記事、プロジェクト、メンバーを検索..."
6778
emptyStateText="検索キーワードを入力..."
6879
noResultsText={(query) => `「${query}」に一致する結果がありません`}
6980
footerNavigateText="移動"

src/lib/data/public/index.remote.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
listPublishedArticles,
77
searchPublishedArticles,
88
} from "$lib/server/database/articles.server";
9-
import { getMemberBySlug, listMembers } from "$lib/server/database/members.server";
9+
import { getMemberBySlug, listMembers, searchMembers } from "$lib/server/database/members.server";
1010
import {
1111
getProjectBySlug,
1212
listProjects,
@@ -34,9 +34,10 @@ export const getPublicMember = query(v.string(), getMemberBySlug);
3434
export const searchPublic = query(
3535
v.string(),
3636
async (searchQuery: string): Promise<SearchResult[]> => {
37-
const [articles, projects] = await Promise.all([
37+
const [articles, projects, members] = await Promise.all([
3838
searchPublishedArticles(searchQuery),
3939
searchProjects(searchQuery),
40+
searchMembers(searchQuery),
4041
]);
4142

4243
const articleResults: SearchResult[] = articles.map((article) => ({
@@ -59,6 +60,14 @@ export const searchPublic = query(
5960
coverUrl: project.coverUrl,
6061
}));
6162

62-
return [...articleResults, ...projectResults];
63+
const memberResults: SearchResult[] = members.map((member) => ({
64+
type: "member" as const,
65+
id: member.id,
66+
slug: member.slug,
67+
name: member.name,
68+
bio: member.bio,
69+
}));
70+
71+
return [...articleResults, ...projectResults, ...memberResults];
6372
},
6473
);

src/lib/shared/logic/search.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ export type SearchResult =
1616
name: string;
1717
description: string | null;
1818
coverUrl: string | null;
19+
}
20+
| {
21+
type: "member";
22+
id: string;
23+
slug: string;
24+
name: string;
25+
bio: string | null;
1926
};
2027

2128
export type AdminSearchResult =
@@ -54,11 +61,16 @@ export function filterSearchResults(results: SearchResult[], query: string): Sea
5461
result.title.toLowerCase().includes(lowerQuery) ||
5562
result.excerpt?.toLowerCase().includes(lowerQuery)
5663
);
57-
} else {
64+
} else if (result.type === "project") {
5865
return (
5966
result.name.toLowerCase().includes(lowerQuery) ||
6067
result.description?.toLowerCase().includes(lowerQuery)
6168
);
69+
} else {
70+
return (
71+
result.name.toLowerCase().includes(lowerQuery) ||
72+
result.bio?.toLowerCase().includes(lowerQuery)
73+
);
6274
}
6375
});
6476
}

src/routes/(site)/search/+page.svelte

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
99
const articleResults = $derived(results.filter((r) => r.type === "article"));
1010
const projectResults = $derived(results.filter((r) => r.type === "project"));
11+
const memberResults = $derived(results.filter((r) => r.type === "member"));
1112
</script>
1213

1314
<svelte:head>
@@ -45,7 +46,7 @@
4546
{#each articleResults as article (article.id)}
4647
<a
4748
href="/articles/{article.slug}"
48-
class="group rounded-xl border border-zinc-200 bg-white p-6 transition-all hover:border-[#00D372] hover:shadow-md"
49+
class="group rounded-xl border border-zinc-200/50 bg-white/80 backdrop-blur-md p-6 transition-all hover:border-[#00D372] hover:shadow-md"
4950
>
5051
{#if article.coverUrl}
5152
<img
@@ -76,13 +77,13 @@
7677
{/if}
7778

7879
{#if projectResults.length > 0}
79-
<section>
80+
<section class="mb-12">
8081
<h2 class="mb-4 text-xl font-semibold">プロジェクト ({projectResults.length}件)</h2>
8182
<div class="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
8283
{#each projectResults as project (project.id)}
8384
<a
8485
href="/projects/{project.slug}"
85-
class="group rounded-xl border border-zinc-200 bg-white p-6 transition-all hover:border-[#00D372] hover:shadow-md"
86+
class="group rounded-xl border border-zinc-200/50 bg-white/80 backdrop-blur-md p-6 transition-all hover:border-[#00D372] hover:shadow-md"
8687
>
8788
{#if project.coverUrl}
8889
<img
@@ -100,5 +101,24 @@
100101
</div>
101102
</section>
102103
{/if}
104+
105+
{#if memberResults.length > 0}
106+
<section>
107+
<h2 class="mb-4 text-xl font-semibold">メンバー ({memberResults.length}件)</h2>
108+
<div class="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
109+
{#each memberResults as member (member.id)}
110+
<a
111+
href="/members/{member.slug}"
112+
class="group rounded-xl border border-zinc-200/50 bg-white/80 backdrop-blur-md p-6 transition-all hover:border-[#00D372] hover:shadow-md"
113+
>
114+
<h3 class="mb-2 font-semibold group-hover:text-[#00D372]">{member.name}</h3>
115+
{#if member.bio}
116+
<p class="mb-4 line-clamp-2 text-sm text-zinc-500">{member.bio}</p>
117+
{/if}
118+
</a>
119+
{/each}
120+
</div>
121+
</section>
122+
{/if}
103123
{/if}
104124
</div>

0 commit comments

Comments
 (0)