From 754246e3951bdd8885d67032124cc8a149e5bab4 Mon Sep 17 00:00:00 2001 From: zhangzhenghao Date: Sun, 26 Apr 2026 15:54:16 +0800 Subject: [PATCH 1/6] feat: add Extensions menu with browser links in navigation drawer - Add v-list-group for Extensions in v-navigation-drawer - Include Chrome, Edge, Firefox extension links with icons - Use mdi-puzzle, mdi-google-chrome, mdi-microsoft-edge, mdi-firefox icons --- frontend/src/layouts/MainLayout.vue | 30 +++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/frontend/src/layouts/MainLayout.vue b/frontend/src/layouts/MainLayout.vue index 35e4cbe..2ba45a8 100644 --- a/frontend/src/layouts/MainLayout.vue +++ b/frontend/src/layouts/MainLayout.vue @@ -5,6 +5,36 @@ + + + + + + + + +
From 8f5941e3ce2cd9ce236a8a5ef960619c64dc788c Mon Sep 17 00:00:00 2001 From: zhangzhenghao Date: Sun, 26 Apr 2026 16:02:33 +0800 Subject: [PATCH 2/6] fix: show error message instead of infinite loading on Explore page - Add error state to Home.vue - Add .catch() handlers to recommend() and next() methods - Show v-alert with error message when API fails - Add Retry button for user to retry fetching - Clear error state before new requests --- frontend/src/views/Home.vue | 47 ++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/frontend/src/views/Home.vue b/frontend/src/views/Home.vue index d9ddf4d..c939829 100644 --- a/frontend/src/views/Home.vue +++ b/frontend/src/views/Home.vue @@ -42,7 +42,17 @@
- + + +
+ mdi-alert-circle + {{ error }} +
+ + mdi-refresh + Retry + +
@@ -86,6 +96,7 @@ export default { subscribers_count: 0, language: "", readme: null, + error: null, primaryColor: "blue darken-1", textColor: "white-text text-lighten-3", topic: "", @@ -155,13 +166,22 @@ export default { if (topic == "/cpp") { topic = "/c%2B%2B"; } + this.error = null; console.log("/api/repo" + topic); axios .get("/api/repo" + topic, { withCredentials: true }) .then((response) => { this.setRepository(response.data); + }) + .catch((error) => { + this.error = error.response?.data?.error || "Failed to fetch repository. Please try again."; + console.error("Recommend error:", error); }); }, + retry() { + this.clearRepository(); + this.recommend(); + }, setRepository(repo) { this.item_id = repo.item_id; this.full_name = repo.full_name; @@ -176,6 +196,7 @@ export default { this.item_id = null; this.full_name = ""; this.readme = null; + this.error = null; this.stargazers_count = 0; this.forks_count = 0; this.subscribers_count = 0; @@ -194,6 +215,7 @@ export default { }); }, next() { + this.error = null; axios .post("/api/read/" + this.item_id, { withCredentials: true }) .then(() => { @@ -203,7 +225,15 @@ export default { .get("/api/repo" + this.topic, { withCredentials: true }) .then((response) => { this.setRepository(response.data); + }) + .catch((error) => { + this.error = error.response?.data?.error || "Failed to fetch repository. Please try again."; + console.error("Next repo error:", error); }); + }) + .catch((error) => { + this.error = error.response?.data?.error || "Failed to mark as read. Please try again."; + console.error("Read error:", error); }); }, }, @@ -220,6 +250,21 @@ export default { line-height: 1.5; } +.error-alert { + margin: 20px auto; + max-width: 600px; +} + +.error-alert__content { + display: flex; + align-items: center; + gap: 8px; +} + +.retry-btn { + margin-top: 12px; +} + .markdown-body { box-sizing: border-box; min-width: 200px; From e9a48d5f13183b5ebbba9b2aebdc67837309d509 Mon Sep 17 00:00:00 2001 From: zhangzhenghao Date: Sun, 26 Apr 2026 16:07:24 +0800 Subject: [PATCH 3/6] fix: sync auth state between components on login/logout - MainLayout dispatches 'gitrec-auth-change' custom event on logout - MainLayout also dispatches event on successful login check - Home.vue listens for the event and updates isAuthenticated state - Fixes issue where Explore page showed login prompt after logout --- frontend/src/layouts/MainLayout.vue | 3 +++ frontend/src/views/Home.vue | 12 ++++++++++++ 2 files changed, 15 insertions(+) diff --git a/frontend/src/layouts/MainLayout.vue b/frontend/src/layouts/MainLayout.vue index 2ba45a8..84fcf23 100644 --- a/frontend/src/layouts/MainLayout.vue +++ b/frontend/src/layouts/MainLayout.vue @@ -237,6 +237,7 @@ export default { login: response.data.login, timestamp: Date.now() })); + window.dispatchEvent(new CustomEvent('gitrec-auth-change', { detail: { authenticated: true } })); } else { localStorage.removeItem("gitrec_auth_state"); } @@ -265,6 +266,8 @@ export default { await axios.get("/api/logout"); localStorage.removeItem("gitrec_auth_state"); this.isAuthenticated = false; + // Dispatch logout event for other components + window.dispatchEvent(new CustomEvent('gitrec-auth-change', { detail: { authenticated: false } })); this.$router.push("/"); } catch (error) { console.error("Logout failed:", error); diff --git a/frontend/src/views/Home.vue b/frontend/src/views/Home.vue index c939829..9571554 100644 --- a/frontend/src/views/Home.vue +++ b/frontend/src/views/Home.vue @@ -124,8 +124,20 @@ export default { async mounted() { await this.checkAuth(); this.recommend(); + + // Listen for auth change events from MainLayout + window.addEventListener('gitrec-auth-change', this.handleAuthChange); + }, + beforeUnmount() { + window.removeEventListener('gitrec-auth-change', this.handleAuthChange); }, methods: { + handleAuthChange(event) { + this.isAuthenticated = event.detail.authenticated; + if (!this.isAuthenticated) { + this.hideLoginPrompt = false; + } + }, goToLogin() { this.$router.push("/login"); }, From 952927ae695ba94bc67ee8f2fb944585cd3c2a82 Mon Sep 17 00:00:00 2001 From: zhangzhenghao Date: Sun, 26 Apr 2026 16:18:54 +0800 Subject: [PATCH 4/6] refactor: Vue code review optimizations - Extract auth logic into authMixin.js (DRY principle) - Remove unused variables (primaryColor, textColor, stargazers_url, forks_url) - Add loading states for like/next buttons - Add error handling for like() method - Use scoped styles to prevent CSS pollution - Extract constants (TOPICS, LANGUAGES, EXTENSIONS) - Add formatNumber utility for star counts - Use computed topicPath for URL encoding - Use Promise chaining in next() method - Remove console.log statements --- frontend/src/layouts/MainLayout.vue | 179 +++++++++------------------- frontend/src/mixins/authMixin.js | 79 ++++++++++++ frontend/src/views/Home.vue | 160 ++++++++++--------------- 3 files changed, 200 insertions(+), 218 deletions(-) create mode 100644 frontend/src/mixins/authMixin.js diff --git a/frontend/src/layouts/MainLayout.vue b/frontend/src/layouts/MainLayout.vue index 84fcf23..402f387 100644 --- a/frontend/src/layouts/MainLayout.vue +++ b/frontend/src/layouts/MainLayout.vue @@ -16,35 +16,20 @@ - - - -
- - -
-
- +
- + +
@@ -59,9 +44,9 @@ GitRec
- Explore - Trending - Favorites + Explore + Trending + Favorites - - @@ -147,47 +124,54 @@ - diff --git a/frontend/src/views/Favorites.vue b/frontend/src/views/Favorites.vue index 9839bb1..5e255cb 100644 --- a/frontend/src/views/Favorites.vue +++ b/frontend/src/views/Favorites.vue @@ -1,33 +1,41 @@