From 0037b0d3041b09063c9c9bb00a5c1e51abfb842e Mon Sep 17 00:00:00 2001 From: Sluijsens Date: Sat, 1 Aug 2026 00:10:21 +0200 Subject: [PATCH] Herstructureer src/ naar feature-based folderstructuur Volgt de aanpak uit het React 2025 folder structure artikel en het SlpModularCms/frontend referentieproject: components/{layout,ui,shared}, features/landing/{components,data,hooks,pages,__tests__}, en lib/ voor de query client. routes/index.tsx wordt een dunne wrapper rond de nieuwe features/landing/pages/LandingPage.tsx. --- src/components/{ => layout}/Footer.tsx | 0 src/components/{ => layout}/Nav.tsx | 6 +++--- src/components/{ => layout}/RootLayout.tsx | 4 ++-- .../{ => layout}/__tests__/Nav.test.tsx | 2 +- src/components/{ => shared}/ErrorBoundary.tsx | 0 .../{ => shared}/SentryTestButton.tsx | 0 .../{ => shared}/UmamiAnalytics.tsx | 0 .../__tests__/ErrorBoundary.test.tsx | 0 .../__tests__/SentryTestButton.test.tsx | 0 .../__tests__/UmamiAnalytics.test.tsx | 0 src/components/{ => ui}/ThemeToggle.tsx | 2 +- .../__tests__/PackagesSection.test.tsx | 4 ++-- .../landing}/components/AboutSection.tsx | 0 .../landing}/components/ContactSection.tsx | 0 .../landing}/components/Hero.tsx | 2 +- .../landing}/components/PackageCard.tsx | 2 +- .../landing}/components/PackagesSection.tsx | 0 .../landing}/components/ProcessSection.tsx | 0 .../landing}/components/ProcessStep.tsx | 0 src/{ => features/landing}/data/content.ts | 2 +- .../landing}/hooks/usePackagesQuery.ts | 0 src/features/landing/pages/LandingPage.tsx | 17 ++++++++++++++++ src/{ => lib}/queryClient.ts | 0 src/routes/__root.tsx | 6 +++--- src/routes/index.tsx | 20 ++----------------- 25 files changed, 34 insertions(+), 33 deletions(-) rename src/components/{ => layout}/Footer.tsx (100%) rename src/components/{ => layout}/Nav.tsx (95%) rename src/components/{ => layout}/RootLayout.tsx (74%) rename src/components/{ => layout}/__tests__/Nav.test.tsx (97%) rename src/components/{ => shared}/ErrorBoundary.tsx (100%) rename src/components/{ => shared}/SentryTestButton.tsx (100%) rename src/components/{ => shared}/UmamiAnalytics.tsx (100%) rename src/components/{ => shared}/__tests__/ErrorBoundary.test.tsx (100%) rename src/components/{ => shared}/__tests__/SentryTestButton.test.tsx (100%) rename src/components/{ => shared}/__tests__/UmamiAnalytics.test.tsx (100%) rename src/components/{ => ui}/ThemeToggle.tsx (93%) rename src/{components => features/landing}/__tests__/PackagesSection.test.tsx (90%) rename src/{ => features/landing}/components/AboutSection.tsx (100%) rename src/{ => features/landing}/components/ContactSection.tsx (100%) rename src/{ => features/landing}/components/Hero.tsx (96%) rename src/{ => features/landing}/components/PackageCard.tsx (96%) rename src/{ => features/landing}/components/PackagesSection.tsx (100%) rename src/{ => features/landing}/components/ProcessSection.tsx (100%) rename src/{ => features/landing}/components/ProcessStep.tsx (100%) rename src/{ => features/landing}/data/content.ts (97%) rename src/{ => features/landing}/hooks/usePackagesQuery.ts (100%) create mode 100644 src/features/landing/pages/LandingPage.tsx rename src/{ => lib}/queryClient.ts (100%) diff --git a/src/components/Footer.tsx b/src/components/layout/Footer.tsx similarity index 100% rename from src/components/Footer.tsx rename to src/components/layout/Footer.tsx diff --git a/src/components/Nav.tsx b/src/components/layout/Nav.tsx similarity index 95% rename from src/components/Nav.tsx rename to src/components/layout/Nav.tsx index d605391..cbbc70d 100644 --- a/src/components/Nav.tsx +++ b/src/components/layout/Nav.tsx @@ -1,7 +1,7 @@ import { useState } from 'react'; -import { navLinks } from '../data/content'; -import { ThemeToggle } from './ThemeToggle'; -import { handleAnchorClick } from '../utils/scrollToHash'; +import { navLinks } from '../../features/landing/data/content'; +import { ThemeToggle } from '../ui/ThemeToggle'; +import { handleAnchorClick } from '../../utils/scrollToHash'; export function Nav() { const [isMenuOpen, setIsMenuOpen] = useState(false); diff --git a/src/components/RootLayout.tsx b/src/components/layout/RootLayout.tsx similarity index 74% rename from src/components/RootLayout.tsx rename to src/components/layout/RootLayout.tsx index 5ae928e..855499d 100644 --- a/src/components/RootLayout.tsx +++ b/src/components/layout/RootLayout.tsx @@ -1,8 +1,8 @@ import type { ReactNode } from 'react'; import { Nav } from './Nav'; import { Footer } from './Footer'; -import { UmamiAnalytics } from './UmamiAnalytics'; -import { SentryTestButton } from './SentryTestButton'; +import { UmamiAnalytics } from '../shared/UmamiAnalytics'; +import { SentryTestButton } from '../shared/SentryTestButton'; export function RootLayout({ children }: { children: ReactNode }) { return ( diff --git a/src/components/__tests__/Nav.test.tsx b/src/components/layout/__tests__/Nav.test.tsx similarity index 97% rename from src/components/__tests__/Nav.test.tsx rename to src/components/layout/__tests__/Nav.test.tsx index 2c75990..d0ebb44 100644 --- a/src/components/__tests__/Nav.test.tsx +++ b/src/components/layout/__tests__/Nav.test.tsx @@ -1,7 +1,7 @@ import { render, screen, fireEvent } from '@testing-library/react'; import { describe, it, expect, beforeEach } from 'vitest'; import { Nav } from '../Nav'; -import { ThemeProvider } from '../../theme/ThemeProvider'; +import { ThemeProvider } from '../../../theme/ThemeProvider'; function renderNav() { return render( diff --git a/src/components/ErrorBoundary.tsx b/src/components/shared/ErrorBoundary.tsx similarity index 100% rename from src/components/ErrorBoundary.tsx rename to src/components/shared/ErrorBoundary.tsx diff --git a/src/components/SentryTestButton.tsx b/src/components/shared/SentryTestButton.tsx similarity index 100% rename from src/components/SentryTestButton.tsx rename to src/components/shared/SentryTestButton.tsx diff --git a/src/components/UmamiAnalytics.tsx b/src/components/shared/UmamiAnalytics.tsx similarity index 100% rename from src/components/UmamiAnalytics.tsx rename to src/components/shared/UmamiAnalytics.tsx diff --git a/src/components/__tests__/ErrorBoundary.test.tsx b/src/components/shared/__tests__/ErrorBoundary.test.tsx similarity index 100% rename from src/components/__tests__/ErrorBoundary.test.tsx rename to src/components/shared/__tests__/ErrorBoundary.test.tsx diff --git a/src/components/__tests__/SentryTestButton.test.tsx b/src/components/shared/__tests__/SentryTestButton.test.tsx similarity index 100% rename from src/components/__tests__/SentryTestButton.test.tsx rename to src/components/shared/__tests__/SentryTestButton.test.tsx diff --git a/src/components/__tests__/UmamiAnalytics.test.tsx b/src/components/shared/__tests__/UmamiAnalytics.test.tsx similarity index 100% rename from src/components/__tests__/UmamiAnalytics.test.tsx rename to src/components/shared/__tests__/UmamiAnalytics.test.tsx diff --git a/src/components/ThemeToggle.tsx b/src/components/ui/ThemeToggle.tsx similarity index 93% rename from src/components/ThemeToggle.tsx rename to src/components/ui/ThemeToggle.tsx index a9dc183..76627f2 100644 --- a/src/components/ThemeToggle.tsx +++ b/src/components/ui/ThemeToggle.tsx @@ -1,4 +1,4 @@ -import { useTheme } from '../theme/ThemeProvider'; +import { useTheme } from '../../theme/ThemeProvider'; /** * Visible theme switcher (requirements FR-3, Functional Design Q1/Q7). diff --git a/src/components/__tests__/PackagesSection.test.tsx b/src/features/landing/__tests__/PackagesSection.test.tsx similarity index 90% rename from src/components/__tests__/PackagesSection.test.tsx rename to src/features/landing/__tests__/PackagesSection.test.tsx index 4605379..e2a56ef 100644 --- a/src/components/__tests__/PackagesSection.test.tsx +++ b/src/features/landing/__tests__/PackagesSection.test.tsx @@ -1,8 +1,8 @@ import { render, screen, waitFor } from '@testing-library/react'; import { describe, it, expect } from 'vitest'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; -import { PackagesSection } from '../PackagesSection'; -import { packages } from '../../data/content'; +import { PackagesSection } from '../components/PackagesSection'; +import { packages } from '../data/content'; function renderWithQueryClient() { const queryClient = new QueryClient(); diff --git a/src/components/AboutSection.tsx b/src/features/landing/components/AboutSection.tsx similarity index 100% rename from src/components/AboutSection.tsx rename to src/features/landing/components/AboutSection.tsx diff --git a/src/components/ContactSection.tsx b/src/features/landing/components/ContactSection.tsx similarity index 100% rename from src/components/ContactSection.tsx rename to src/features/landing/components/ContactSection.tsx diff --git a/src/components/Hero.tsx b/src/features/landing/components/Hero.tsx similarity index 96% rename from src/components/Hero.tsx rename to src/features/landing/components/Hero.tsx index 73f6827..aed59a2 100644 --- a/src/components/Hero.tsx +++ b/src/features/landing/components/Hero.tsx @@ -1,5 +1,5 @@ import { heroContent } from '../data/content'; -import { handleAnchorClick } from '../utils/scrollToHash'; +import { handleAnchorClick } from '../../../utils/scrollToHash'; export function Hero() { return ( diff --git a/src/components/PackageCard.tsx b/src/features/landing/components/PackageCard.tsx similarity index 96% rename from src/components/PackageCard.tsx rename to src/features/landing/components/PackageCard.tsx index 8f3be16..26ac3e6 100644 --- a/src/components/PackageCard.tsx +++ b/src/features/landing/components/PackageCard.tsx @@ -1,5 +1,5 @@ import type { PackageCardData } from '../data/content'; -import { handleAnchorClick } from '../utils/scrollToHash'; +import { handleAnchorClick } from '../../../utils/scrollToHash'; export function PackageCard({ pkg }: { pkg: PackageCardData }) { return ( diff --git a/src/components/PackagesSection.tsx b/src/features/landing/components/PackagesSection.tsx similarity index 100% rename from src/components/PackagesSection.tsx rename to src/features/landing/components/PackagesSection.tsx diff --git a/src/components/ProcessSection.tsx b/src/features/landing/components/ProcessSection.tsx similarity index 100% rename from src/components/ProcessSection.tsx rename to src/features/landing/components/ProcessSection.tsx diff --git a/src/components/ProcessStep.tsx b/src/features/landing/components/ProcessStep.tsx similarity index 100% rename from src/components/ProcessStep.tsx rename to src/features/landing/components/ProcessStep.tsx diff --git a/src/data/content.ts b/src/features/landing/data/content.ts similarity index 97% rename from src/data/content.ts rename to src/features/landing/data/content.ts index 41620d5..a9f3d9e 100644 --- a/src/data/content.ts +++ b/src/features/landing/data/content.ts @@ -7,7 +7,7 @@ * * This module is the current source of truth for content (requirements FR-1/FR-6). * It is deliberately structured so it can be swapped for TanStack Query data later - * (see src/hooks/usePackagesQuery.ts) with minimal changes (requirements FR-5). + * (see src/features/landing/hooks/usePackagesQuery.ts) with minimal changes (requirements FR-5). */ export interface NavLink { diff --git a/src/hooks/usePackagesQuery.ts b/src/features/landing/hooks/usePackagesQuery.ts similarity index 100% rename from src/hooks/usePackagesQuery.ts rename to src/features/landing/hooks/usePackagesQuery.ts diff --git a/src/features/landing/pages/LandingPage.tsx b/src/features/landing/pages/LandingPage.tsx new file mode 100644 index 0000000..b8b4ede --- /dev/null +++ b/src/features/landing/pages/LandingPage.tsx @@ -0,0 +1,17 @@ +import { Hero } from '../components/Hero'; +import { PackagesSection } from '../components/PackagesSection'; +import { ProcessSection } from '../components/ProcessSection'; +import { AboutSection } from '../components/AboutSection'; +import { ContactSection } from '../components/ContactSection'; + +export function LandingPage() { + return ( + <> + + + + + + + ); +} diff --git a/src/queryClient.ts b/src/lib/queryClient.ts similarity index 100% rename from src/queryClient.ts rename to src/lib/queryClient.ts diff --git a/src/routes/__root.tsx b/src/routes/__root.tsx index 3d7612c..43da2cf 100644 --- a/src/routes/__root.tsx +++ b/src/routes/__root.tsx @@ -1,9 +1,9 @@ import { createRootRoute, Outlet } from '@tanstack/react-router'; import { QueryClientProvider } from '@tanstack/react-query'; -import { ErrorBoundary } from '../components/ErrorBoundary'; +import { ErrorBoundary } from '../components/shared/ErrorBoundary'; import { ThemeProvider } from '../theme/ThemeProvider'; -import { RootLayout } from '../components/RootLayout'; -import { queryClient } from '../queryClient'; +import { RootLayout } from '../components/layout/RootLayout'; +import { queryClient } from '../lib/queryClient'; /** * Root route composition (Functional Design / NFR Design logical components): diff --git a/src/routes/index.tsx b/src/routes/index.tsx index 899d617..b9ff12f 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -1,25 +1,9 @@ import { createRoute } from '@tanstack/react-router'; import { rootRoute } from './__root'; -import { Hero } from '../components/Hero'; -import { PackagesSection } from '../components/PackagesSection'; -import { ProcessSection } from '../components/ProcessSection'; -import { AboutSection } from '../components/AboutSection'; -import { ContactSection } from '../components/ContactSection'; - -function IndexPage() { - return ( - <> - - - - - - - ); -} +import { LandingPage } from '../features/landing/pages/LandingPage'; export const indexRoute = createRoute({ getParentRoute: () => rootRoute, path: '/', - component: IndexPage, + component: LandingPage, });