Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

110 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Galerium FullStack

Java 17 Spring Boot 3.x React 18 Vite MySQL 8 Code Style: Prettier

🚀 View Live Demo  |  📄 View GitHub Supabase Repo

A full-stack CRUD application designed for photographers to manage clients, galleries, and sessions. This project was developed as the final project for Module 3 of the IronHack Web Development Bootcamp.

📋 Table of Contents


✨ Key Features

This application was built with a strong focus on a clean user experience and a robust, scalable architecture.

  • Full Client Management: Complete CRUD functionality (Create, Read, Update, Delete) for client records.
  • Dynamic Data Handling:
    • Server-side pagination and sorting for efficient data management.
    • Debounced text search across multiple client fields (name, email, phone).
    • Intuitive, multi-select tag filtering to easily segment clients.
  • Advanced User Experience (UX):
    • User-Centric Feedback: The UI provides constant feedback with flicker-free loading states, clear error messages on API failures, and "no results" notifications.
    • Advanced Tag System: The client form features a tag input with autocomplete, suggesting existing tags to ensure data consistency while still allowing the creation of new ones on the fly.
    • Interactive Modals: Confirmation modals for destructive actions (like deleting) are user-friendly, featuring smooth animations and the ability to close by clicking outside.
    • Image Previews: The client form provides an instant preview for image URLs, with elegant error handling for broken links.
  • Consistent Design System: A unified styling guide with CSS variables ensures a consistent and professional look and feel across all components.

📸 Screenshots

Client list with search, multi-tag filtering, and pagination.
Client Filter Demo


🛠️ Tech Stack

Area Technologies
Frontend React, Vite, React Router, react-hot-toast
Backend Java, Spring Boot, Spring Data JPA, Spring Security
Database MySQL (Production), H2 (Development)
Testing JUnit 5, Mockito (Backend), Vitest, RTL (Frontend)
Tooling Maven, Node.js, ESLint, Prettier
---

🚀 Getting Started Locally

Prerequisites

  • Java 17+
  • Node.js 18+
  • Maven 3+
  • Git

1. Backend Setup

# Clone the repository
git clone https://github.com/AidaG91/Galerium-FullStack.git
cd galerium-fullstack/backend

# Install dependencies and build the project
mvn clean install

# Run the Spring Boot application
mvn spring-boot:run

# The backend will be available at http://localhost:8080
# You can check the health status at: http://localhost:8080/api/health

2. Frontend Setup

# In a new terminal, navigate to the frontend directory
cd ../frontend

# Install dependencies
npm install

# Create the local environment file
cp .env.example .env

# Run the development server
npm run dev

# The application will be available at http://localhost:5173

Configuration

The project uses configuration files for both the backend and frontend.

Backend (backend/src/main/resources/application.properties)

For development, the application uses an in-memory H2 database. For production, you should configure the connection to a MySQL database and set the ddl-auto property to update.

# Development (H2)
spring.jpa.hibernate.ddl-auto=create-drop
spring.datasource.url=jdbc:h2:mem:galeriumdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=

# Production (MySQL Example)
# spring.jpa.hibernate.ddl-auto=update
# spring.datasource.url=jdbc:mysql://localhost:3306/galerium
# spring.datasource.username=root
# spring.datasource.password=yourpassword

Frontend (frontend/.env)

The frontend needs to know the base URL of the backend API. Copy this file to .env for local development.

VITE_API_URL=http://localhost:8080/api

📚 API Endpoints

The core API for the Client resource follows RESTful conventions.

Method Endpoint Description
GET /api/health Checks the database connection status.
GET /api/tags Retrieves a list of all unique tags.
GET /api/clients/paged Lists clients with pagination and sorting.
GET /api/clients/search/paged Searches clients by text query.
GET /api/clients/by-tag Filters clients by one or more tags.
POST /api/clients Creates a new client.
GET /api/clients/{id} Retrieves a single client by ID.
PUT /api/clients/{id} Updates an existing client.
DELETE /api/clients/{id} Deletes a client.
---

🧪 Testing

The project includes tests for both the backend and frontend to ensure code quality and reliability.

Backend Tests

The backend includes both Unit tests for the controller layer (@WebMvcTest) and a full Integration test (@SpringBootTest) that validates the complete CRUD lifecycle against a test database.

# From the /backend directory
mvn test

Frontend Tests

The frontend uses Vitest and React Testing Library to test critical components. The tests cover rendering the client list from a mocked API and verifying the "no results" state.

# From the /frontend directory
npm test
---

🛠️ Development Tooling & Quality Assurance

This project is configured with modern tools to ensure code quality, consistency, and a productive development experience. All dependencies are included in the respective package.json and pom.xml files.

  • ESLint: Used for static code analysis to find and fix problems in the JavaScript/React code. The configuration is based on the modern "flat config" (eslint.config.js).
  • Prettier: Integrated for automated code formatting, ensuring a consistent style across the entire codebase.
  • Vitest & React Testing Library: A modern testing framework is set up for the frontend, allowing for fast and reliable component testing in a simulated DOM environment (jsdom).

🏗️ Architectural Decisions

Frontend Architecture

  • Scalable CSS with CSS Modules: Prevents style conflicts and ensures components are self-contained.
  • Reusable Global Styles: A base design system is established in index.css, including a centralized color palette with CSS variables and global utility classes for common elements like buttons (.btn, .btn--primary), promoting a DRY (Don't Repeat Yourself) codebase.
  • Centralized API Logic: All fetch calls to the backend are managed in a dedicated service file (src/api/clientService.js), separating API communication logic from the UI components for better maintainability.

Backend Architecture

  • Robust Entity Relationships (@ManyToMany): For the tags feature, a @ManyToMany relationship between the Client and Tag entities was implemented. This architecture ensures data integrity, prevents tag duplication, and provides a scalable foundation for advanced filtering.
  • Service Layer Intelligence: The logic for managing tags (finding existing ones or creating new ones) is centralized in the service layer (ClientService), keeping the controllers slim and focused on handling HTTP requests.
  • Data Seeding on Startup: A DataLoader component uses CommandLineRunner to populate the database with realistic sample data on application startup, facilitating easy testing and development.
---

🏆 Challenges & Learnings

This project was a deep dive into full-stack development and presented several real-world challenges that were crucial for my learning.

  • Performance Optimization (N+1 Query Problem):

    • Challenge: The initial implementation of the client list was extremely inefficient. It performed one query to fetch the clients and then N additional queries to fetch the tags for each client.
    • Solution: I refactored the Spring Data JPA repository to use a custom @Query with LEFT JOIN FETCH. This allowed Hibernate to retrieve clients and their associated tags in a single, efficient database call, dramatically improving performance.
  • Debugging the "Silent" 500 Error:

    • Challenge: The most difficult challenge was a persistent 500 Internal Server Error during client creation that produced no error log in the backend console. This led to a long "blind" debugging session where I explored issues in the database, security, and entity relationships.
    • Solution: The root cause was twofold: a simple validation rule (@Size(min=5) on an optional field) and a GlobalExceptionHandler that was catching the exception but failing to log it. The key takeaway was immense: an unlogged error is a developer's worst enemy. I learned the critical importance of robust logging in every exception handler, which was the final key to diagnosing and fixing the bug.
---

🗂️ Project Structure

Click to view the full project structure
.
|   PreguntaEntrevista.md
|   README.md
|
+---backend
|   |   .env.example
|   |   mvnw
|   |   mvnw.cmd
|   |   pom.xml
|   |
|   +---assets
|   |       class_diagram_Galerium.png
|   |
|   \---src
|       +---main
|       |   +---java
|       |   |   \---galerium
|       |   |       |   GaleriumApplication.java
|       |   |       |
|       |   |       +---config
|       |   |       |       GlobalExceptionHandler.java
|       |   |       |       SecurityConfig.java
|       |   |       |       WebConfig.java
|       |   |       |
|       |   |       +---controller
|       |   |       |       ClientController.java
|       |   |       |       HealthController.java
|       |   |       |       TagController.java
|       |   |       |       (and other controllers...)
|       |   |       |
|       |   |       +---dto
|       |   |       |   +---client
|       |   |       |   |       ClientRequestDTO.java
|       |   |       |   |       ClientResponseDTO.java
|       |   |       |   |       ClientUpdateDTO.java
|       |   |       |   |
|       |   |       |   \---(other DTOs...)
|       |   |       |
|       |   |       +---enums
|       |   |       |       UserRole.java
|       |   |       |
|       |   |       +---model
|       |   |       |       Client.java
|       |   |       |       Tag.java
|       |   |       |       User.java
|       |   |       |       (and other models...)
|       |   |       |
|       |   |       +---repository
|       |   |       |       ClientRepository.java
|       |   |       |       TagRepository.java
|       |   |       |       UserRepository.java
|       |   |       |       (and other repositories...)
|       |   |       |
|       |   |       +---service
|       |   |       |   +---impl
|       |   |       |   |       ClientServiceImpl.java
|       |   |       |   |       TagServiceImpl.java
|       |   |       |   |       (and other services...)
|       |   |       |   |
|       |   |       |   \---interfaces
|       |   |       |           ClientService.java
|       |   |       |           TagService.java
|       |   |       |           (and other interfaces...)
|       |   |       |
|       |   |       \---util
|       |   |               DataLoader.java
|       |   |               OpenApiConfig.java
|       |   |
|       |   \---resources
|       |           application.properties
|       |
|       \---test
|           \---java
|               \---galerium
|                       (test files...)
|
+---docs
|   \---images
|           filter-demo.gif
|
\---frontend
    |   .env
    |   .env.example
    |   eslint.config.js
    |   index.html
    |   package.json
    |   vite.config.js
    |
    +---public
    |       galerium-favicon.png
    |       galerium-logo-text.png
    |
    +---src
    |   |   App.jsx
    |   |   index.css
    |   |   main.jsx
    |   |   setupTests.js
    |   |
    |   +---api
    |   |       clientService.js
    |   |
    |   +---components
    |   |       ClientCRUD.jsx
    |   |       ClientForm.jsx
    |   |       DeleteModal.jsx
    |   |       Sidebar.jsx
    |   |
    |   +---layouts
    |   |       SidebarLayout.jsx
    |   |
    |   +---pages
    |   |       ClientDetailPage.jsx
    |   |       ClientFormPage.jsx
    |   |       ClientsPage.jsx
    |   |       Dashboard.jsx
    |   |       LandingPage.jsx
    |   |
    |   +---routes
    |   |       AppRouter.jsx
    |   |
    |   \---styles
    |           ClientCRUD.module.css
    |           (and other style files...)
    |
    \---tests
            ClientsPage.test.jsx

📈 Project Management & Presentation

Project planning and progress were tracked using the Atlassian suite.

---

👤 Author

Aïda García: Junior Web Developer, among other things. Check my gitHub profile 😊

About

IronHack's Module 3 Final Project - FullStack for my own app: Photoshoots and client management for photographers

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages