diff --git a/components/AppHeader.vue b/components/AppHeader.vue index bba8b2e..7b62fdd 100644 --- a/components/AppHeader.vue +++ b/components/AppHeader.vue @@ -6,11 +6,7 @@ const showLogo = ref(true); const { data: profile } = await useFetch("/api/profile"); -const titles = computed(() => [ - profile.value?.bio, - "Open Source Contributor", - "Web3 & Blockchain Enthusiast", -]); +const titles = computed(() => profile.value?.bio.split(",")); + +
+ +
+ Showing + of + + projects + with +
+ + + + + +
+ + + + + + + diff --git a/components/project/TopicFilterNav.vue b/components/project/TopicFilterNav.vue index 15b407b..a36ddb5 100644 --- a/components/project/TopicFilterNav.vue +++ b/components/project/TopicFilterNav.vue @@ -4,7 +4,7 @@ import { Topic } from "server/types/repo"; const emit = defineEmits(["update:modelValue"]); const props = defineProps<{ - modelValue: string; + modelValue: string | null; topics: Topic[]; }>(); diff --git a/components/ui/Button.vue b/components/ui/Button.vue index bf4669b..41fb91b 100644 --- a/components/ui/Button.vue +++ b/components/ui/Button.vue @@ -11,6 +11,7 @@ defineProps<{ large?: boolean; small?: boolean; tiny?: boolean; + micro?: boolean; }>(); @@ -28,6 +29,7 @@ defineProps<{ 'btn-lg': large, 'btn-sm': small, 'btn-xs': tiny, + 'btn-xs !h-5 !min-h-min': micro, }" @click="$emit('click')" > diff --git a/components/ui/Collapse.vue b/components/ui/Collapse.vue index 62e9dad..824ef6e 100644 --- a/components/ui/Collapse.vue +++ b/components/ui/Collapse.vue @@ -3,7 +3,7 @@ import { AccordionInjection } from "types/ui"; const props = defineProps<{ title: string; - open: boolean; + open?: boolean; }>(); const open = ref(props.open); diff --git a/components/ui/Countdown.vue b/components/ui/Countdown.vue new file mode 100644 index 0000000..61df25e --- /dev/null +++ b/components/ui/Countdown.vue @@ -0,0 +1,11 @@ + + + diff --git a/components/ui/Divider.vue b/components/ui/Divider.vue index 4095d0d..67f9932 100644 --- a/components/ui/Divider.vue +++ b/components/ui/Divider.vue @@ -1,7 +1,7 @@ diff --git a/package-lock.json b/package-lock.json index e818dd3..5264a6f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,7 @@ "vue3-particles": "^2.12.0" }, "devDependencies": { - "@nuxt/devtools": "*", + "@nuxt/devtools": "latest", "@nuxtjs/tailwindcss": "^6.8.0", "@types/node": "^20.5.3", "daisyui": "^3.5.1", diff --git a/server/api/languages.ts b/server/api/languages.ts index 8e247e0..3e1c9a0 100644 --- a/server/api/languages.ts +++ b/server/api/languages.ts @@ -36,6 +36,6 @@ const collectLanguages = (repos: Repo[]): Language[] => { // add rate to each language return Object.values(list).map((language) => ({ ...language, - rate: (language.lines / lineSum) * 100, + rate: calculateRate(language.lines, lineSum), })); }; diff --git a/server/api/repos.ts b/server/api/repos.ts index e0b2b0d..6dbfdc0 100644 --- a/server/api/repos.ts +++ b/server/api/repos.ts @@ -60,7 +60,7 @@ const normalizeLanguages = (data: LanguageData): Language[] => { return entries.map(([name, lines]) => ({ name, lines, - rate: ((lines / lineSum) * 100).toFixed(1) as any, + rate: calculateRate(lines, lineSum), color: COLORS[name] ?? null, })); }; diff --git a/server/utils/calculateRate.ts b/server/utils/calculateRate.ts new file mode 100644 index 0000000..f55bd45 --- /dev/null +++ b/server/utils/calculateRate.ts @@ -0,0 +1,2 @@ +export const calculateRate = (value: number, total: number) => + +((value / total) * 100).toFixed(1); diff --git a/store/repository.ts b/store/repository.ts index 6acbc64..b6f88fd 100644 --- a/store/repository.ts +++ b/store/repository.ts @@ -10,8 +10,17 @@ export const useRepositoryStore = defineStore('repository', () => { const topicStore = useTopicStore(); const languageStore = useLanguageStore(); + // pagination states + const page = ref(1); + const perPage = ref(5); + const total = computed(() => filteredRepositories.value.length); + const hasMore = computed(() => total.value > page.value * perPage.value); + const hasFilter = computed( + () => !!languageStore.selected || !!topicStore.selected + ); + // getters - const repositories = computed(() => { + const filteredRepositories = computed(() => { let repos = _repositories.value; // filter by language @@ -21,6 +30,9 @@ export const useRepositoryStore = defineStore('repository', () => { (lang) => lang.name === languageStore.selected ) ); + + // reset page on filter + page.value = 1; } // filter by topics @@ -28,11 +40,18 @@ export const useRepositoryStore = defineStore('repository', () => { repos = repos.filter((repo) => repo.topics.includes(topicStore.selected as any) ); + + // reset page on filter + page.value = 1; } return repos; }); + const repositories = computed(() => + filteredRepositories.value.slice(0, page.value * perPage.value) + ); + // actions async function load() { loading.value = true; @@ -41,9 +60,20 @@ export const useRepositoryStore = defineStore('repository', () => { loading.value = false; } + function loadMore() { + page.value++; + } + // init load(); // public api - return { load, loading, repositories }; + return { + loadMore, + loading, + repositories, + hasFilter, + hasMore, + total, + }; });