Skip to content
Open
Changes from all commits
提交
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 67 additions & 24 deletions components/仓库List.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ import { 仓库 } from "../types";
import { LanguageFilter } from "./LanguageFilter";
import { 仓库Item } from "./仓库Item";
import { SDGFilter } from "./SDGFilter";
import {Grid, Stack} from '@primer/react-brand';

import { Grid, Stack } from "@primer/react-brand";

type 仓库ListProps = {
repositories: 仓库[];
Expand All @@ -29,36 +28,57 @@ export const 仓库List = ({ repositories, filter }: 仓库ListProps) =>
const [selectedLanguages, setSelectedLanguages] = useState<string[]>([]);
const [selectedTopics, setSelectedTopics] = useState<string[]>([]);


const filtered仓库 = repositories.filter((repository) => {
const languageFilter =
selectedLanguages.length === 0 || selectedLanguages.includes(repository.language.display);
selectedLanguages.length === 0 ||
selectedLanguages.includes(repository.language.display);

const topicFilter =
selectedTopics.length === 0 ||
repository.topics?.some((topic) => selectedTopics.includes(topic.display));
repository.topics?.some((topic) =>
selectedTopics.includes(topic.display)
);

const nameFilter = Object.values(repository).some(
(value) => value && value.toString().toLowerCase().includes(filter.toLowerCase())
(value) =>
value &&
value.toString().toLowerCase().includes(filter.toLowerCase())
);

const happyContainer = Object.values(repository).some(
(value) => value && value.toString().toLowerCase().includes(filter.toLowerCase())
(value) =>
value &&
value.toString().toLowerCase().includes(filter.toLowerCase())
);

return languageFilter && nameFilter && topicFilter && happyContainer;
});

// ✅ 仓库 count logic
const totalCount = repositories.length;
const visibleCount = filtered仓库.length;

const uniqueLanguages = [
...new Set(repositories.map((repository) => repository.language.display))
...new Set(repositories.map((repository) => repository.language.display)),
];
const languageOptions = uniqueLanguages.map((language) => ({ value: language, label: language }));
const languageOptions = uniqueLanguages.map((language) => ({
value: language,
label: language,
}));

const uniqueTopics = [
...new Set(
repositories.flatMap((repository) => repository.topics?.map((topic) => topic.display) ?? [])
)
repositories.flatMap(
(repository) =>
repository.topics?.map((topic) => topic.display) ?? []
)
),
].sort((a, b) => parseInt(a.slice(4)) - parseInt(b.slice(4)));
const topicOptions = uniqueTopics.map((topic) => ({ value: topic, label: IndexedTopics[topic] }));

const topicOptions = uniqueTopics.map((topic) => ({
value: topic,
label: IndexedTopics[topic],
}));

const loadMoreItems = () => setItems(items + itemsPerScroll);
const hasMoreItems = items < filtered仓库.length;
Expand All @@ -67,26 +87,49 @@ export const 仓库List = ({ repositories, filter }: 仓库ListProps) =>
<main className="repoWrap">
<div className="grid-wrap">
<Grid>
<Grid.Column span={{xsmall: 12, small: 12, medium: 12, large: 5, xlarge: 3}}>
{/* LEFT COLUMN – FILTERS */}
<Grid.Column
span={{ xsmall: 12, small: 12, medium: 12, large: 5, xlarge: 3 }}
>
<Stack className="stack">
<LanguageFilter
setSelectedLanguages={setSelectedLanguages}
languageOptions={languageOptions}
/>
<SDGFilter setSelectedTopics={setSelectedTopics} topicOptions={topicOptions} />
<SDGFilter
setSelectedTopics={setSelectedTopics}
topicOptions={topicOptions}
/>
</Stack>
</Grid.Column>
<Grid.Column className="repo-list-wrap" span={{xsmall: 12, small: 12, medium: 12, large: 7, xlarge: 9}}>
<InfiniteScroll
dataLength={items}
next={loadMoreItems}
hasMore={hasMoreItems}
loader={<Loader />}
>
{filtered仓库.slice(0, items).map((repository) => (
<仓库Item key={repository.id} repository={repository} />

{/* RIGHT COLUMN – REPOSITORY LIST */}
<Grid.Column
className="repo-list-wrap"
span={{ xsmall: 12, small: 12, medium: 12, large: 7, xlarge: 9 }}
>
{/* ✅ STEP 5: 仓库 count indicator */}
<p className="text-sm text-gray-500 mb-3">
{visibleCount === totalCount
? `Showing ${totalCount} repositories`
: `Showing ${visibleCount} of ${totalCount} repositories`}
</p>

<InfiniteScroll
dataLength={items}
next={loadMoreItems}
hasMore={hasMoreItems}
loader={<Loader />}
>
{filtered仓库
.slice(0, items)
.map((repository) => (
<仓库Item
key={repository.id}
repository={repository}
/>
))}
</InfiniteScroll>
</InfiniteScroll>
</Grid.Column>
</Grid>
</div>
Expand Down