Skip to content

Commit 0db65ce

Browse files
authored
refactor: use Junie coding agent to refactor vue3 app (#253)
* feat: introduce API caching, error handling, and new views - Add VueUse `createFetch` with in-memory TTL caching and retries for API calls. - Replace direct REST calls with shared API utilities across stores. - Introduce Error and 404 views with Carbon styling and a global error handler. - Enhance views with inline error notifications and loading skeletons. - Update docs with Feature-Sliced Design suggestions for scalable architecture. Signed-off-by: David Nixon <[email protected]> * fix: lock file Signed-off-by: David Nixon <[email protected]> * refactor: junie migrate from JavaScript to TypeScript Signed-off-by: David Nixon <[email protected]> * chore: rebase Signed-off-by: David Nixon <[email protected]> * chore: rebase Signed-off-by: David Nixon <[email protected]> * refactor: remove unused icon components and migrate hobby implementation to lazy-loaded component Signed-off-by: David Nixon <[email protected]> * refactor: the Junie agent- improve type safety and modularity across app Signed-off-by: David Nixon <[email protected]> * refactor: agent Junie - modularize shared components and composables for improved reusability Signed-off-by: David Nixon <[email protected]> * refactor: agent Junie - modularize rarity handling with RarityStars and StepIcon components Signed-off-by: David Nixon <[email protected]> * refactor: update e2e Signed-off-by: David Nixon <[email protected]> * refactor: rebase Signed-off-by: David Nixon <[email protected]> --------- Signed-off-by: David Nixon <[email protected]>
1 parent 3641d44 commit 0db65ce

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+1832
-1238
lines changed

apps/hello-carbon-vue3/README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ checkout [Hello carbon 11 web components with Vue 3](https://github.com/davidnix
1515
- [Pinia](https://pinia.vuejs.org/) — this replaces Vuex store
1616
- [i18next](https://www.i18next.com/) — this repo demonstrates how to include translations using i18next. All UI
1717
elements are translated and most content is translated.
18-
- [fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch) — REST calls via fetch
19-
- [@vueuse](https://vueuse.org/) — Lazy image loading, manage local storage, and many other useful utilities
18+
- [@vueuse](https://vueuse.org/) — Lazy image loading, manage local storage, useFetch wrapper for API with caching, and many other useful utilities
2019
- [cypress](https://www.cypress.io/) — Implement e2e tests with cypress to help screen PRs
2120

2221
## Carbon styles
@@ -27,6 +26,11 @@ See [\_carbon-90.scss](./src/styles/_carbon-90.scss) for instructions on creatin
2726

2827
## Pages & Components
2928

29+
New in this iteration:
30+
- API calls use a shared VueUse createFetch instance with in-memory TTL caching and simple retries (see src/shared/api/http.js). Pages now show loading skeletons and Carbon inline error notifications when API calls fail.
31+
- Added dedicated Error and 404 pages styled in Carbon (routes: /error and catch-all).
32+
- Suggestions for Feature-Sliced Design structure are documented in docs/feature-sliced.md.
33+
3034
[This repo demo site](https://ibm.github.io/hello-carbon-vue3/hello-carbon-vue3/)
3135

3236
- Header with Side nav ![header](../docs/header-bar.jpg)

apps/hello-carbon-vue3/cypress.config.js

Lines changed: 0 additions & 10 deletions
This file was deleted.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { defineConfig } from "cypress";
2+
3+
export default defineConfig({
4+
e2e: {
5+
specPattern: "cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}",
6+
baseUrl: "http://localhost:5173",
7+
},
8+
component: {
9+
specPattern: "src/**/__tests__/*.{cy,spec}.{js,ts,jsx,tsx}",
10+
devServer: {
11+
framework: "vue",
12+
bundler: "vite",
13+
},
14+
},
15+
});

apps/hello-carbon-vue3/cypress/e2e/smoke.cy.js renamed to apps/hello-carbon-vue3/cypress/e2e/smoke.cy.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ describe("smoke test", () => {
2020
// villagers
2121
cy.get("#side-nav").find("li").eq(4).click();
2222
cy.location("pathname").should("eq", "/villagers");
23-
cy.get("[data-cy=\"hobby\"]").should("have.length", 6);
23+
// only 1 hobby section is loaded at a time
24+
cy.get("[data-cy=\"hobby\"]").should("have.length", 1);
2425

2526
// home
2627
cy.get("#side-nav").find("li").first().click();

apps/hello-carbon-vue3/cypress/support/commands.js renamed to apps/hello-carbon-vue3/cypress/support/commands.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
/// <reference types="cypress" />
12
// ***********************************************
2-
// This example commands.js shows you how to
3+
// This example commands.ts shows you how to
34
// create various custom commands and overwrite
45
// existing commands.
56
//
@@ -23,3 +24,16 @@
2324
//
2425
// -- This will overwrite an existing command --
2526
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
27+
//
28+
// declare global {
29+
// namespace Cypress {
30+
// interface Chainable {
31+
// login(email: string, password: string): Chainable<void>
32+
// drag(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
33+
// dismiss(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
34+
// visit(originalFn: CommandOriginalFn, url: string, options: Partial<VisitOptions>): Chainable<Element>
35+
// }
36+
// }
37+
// }
38+
39+
export {};

apps/hello-carbon-vue3/cypress/support/e2e.js renamed to apps/hello-carbon-vue3/cypress/support/e2e.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// ***********************************************************
2-
// This example support/e2e.js is processed and
2+
// This example support/index.js is processed and
33
// loaded automatically before your test files.
44
//
55
// This is a great place to put global configuration and
@@ -13,7 +13,7 @@
1313
// https://on.cypress.io/configuration
1414
// ***********************************************************
1515

16-
// Import commands.js using ES2015 syntax:
16+
// Import commands.ts using ES2015 syntax:
1717
import "./commands";
1818

1919
// Alternatively you can use CommonJS syntax:
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"extends": "@vue/tsconfig/tsconfig.dom.json",
3+
"include": ["./e2e/**/*", "./support/**/*"],
4+
"exclude": ["./support/component.*"],
5+
"compilerOptions": {
6+
"isolatedModules": false,
7+
"types": ["cypress"]
8+
}
9+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Components review and split suggestions
2+
3+
- FishView.vue: quite large, but most templating delegates to FishRow. Consider moving pagination and sorting logic into a feature module (features/fish/table) with a composable (useFishTable) and smaller presentational subcomponents.
4+
- VillagersView.vue: contains hobby-specific icon logic and content-switcher wiring. Consider extracting:
5+
- entities/villager/ui/VillagerHobbyList.vue (renders the switcher and content)
6+
- features/villagers/special-icons (encapsulate animated icons rules)
7+
- a composable useVillagerGroups to compute groups and selected tab.
8+
- TheHeader.vue: encapsulates multiple panels and static data. Consider:
9+
- widgets/header/model/useHeaderState.ts for language/login state
10+
- widgets/header/ui/HeaderNav.vue, HeaderPanels.vue for structure.
11+
- SongCard.vue, BugCard.vue, FishRow.vue, VillagerCard.vue are reasonably focused; keep as entities/* UI.
12+
- BlurImage.vue is shared UI primitive; move to shared/ui/BlurImage.vue.
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Feature-Sliced Design (FSD) suggestions
2+
3+
This app is small, but adopting a few FSD ideas will keep it scalable.
4+
5+
## Current structure (selected)
6+
- src/components/* — presentational widgets and feature bits are mixed
7+
- src/views/* — route pages
8+
- src/stores/* — Pinia stores
9+
- src/shared/api/http.js — API helper
10+
- src/composables/* — breakpoints, etc.
11+
12+
## Suggested structure
13+
14+
- src/app/
15+
- index (main.js), App.vue, router, providers, global styles
16+
- src/pages/
17+
- Home, Fish, Bugs, Villagers, Error, NotFound (page-level components only)
18+
- src/widgets/
19+
- Header, ThemeSwitcher, MobileTablePagination (can compose features and entities)
20+
- src/features/
21+
- fish/hide-fish (buttons and logic to hide fish)
22+
- villagers/switcher (content switcher controls)
23+
- src/entities/
24+
- fish, bug, villager, song (cards, rows, basic UI bound to an entity)
25+
- src/shared/
26+
- api (createFetch, fetchJsonCached)
27+
- ui (primitive shared UI, e.g., BlurImage)
28+
- lib (composables, utils: useBreakpoints)
29+
- config (constants, env)
30+
31+
Migration can be incremental: introduce folders and move the most entangled pieces as you touch them. Keep import aliases (@/app, @/pages, etc.) in vite.config.
32+
33+
## Additional notes
34+
- Keep stores under entities, e.g., src/entities/fish/model (Pinia store)
35+
- Page components should orchestrate, not host complex logic: move logic into features/entities.
36+
- Reusability ladder: shared < entities < features < widgets < pages < app.

apps/hello-carbon-vue3/eslint.config.js

Lines changed: 0 additions & 49 deletions
This file was deleted.

0 commit comments

Comments
 (0)