A modern Progressive Web Application (PWA) for managing charitable donations, built using Next.js, TypeScript, and TailwindCSS. This project follows Clean Architecture principles to ensure a clean, scalable, and maintainable codebase.
- Clean Architecture: Organized into layers for scalability and clarity.
- Progressive Web App (PWA): Offline support enabled with
next-pwa
. - GraphQL with Apollo Client: Efficient data fetching and management.
- Zustand State Management: Lightweight and efficient global state management.
- TailwindCSS: Modern, responsive, and utility-first styling.
- Reusable Components: Modular, consistent, and reusable UI components.
- TypeScript: Static typing for better development and fewer runtime errors.
The project is organized following Clean Architecture principles:
charity-pwa/
├── public/ # Static assets
├── src/
│ ├── domain/ # Domain layer
│ │ ├── entities/ # Core business entities (Donation, Metric)
│ │ ├── enums/ # Enums for domain logic
│ │ └── interfaces/ # TypeScript interfaces
│ │
│ ├── application/ # Application layer (use cases)
│ │ └── donation/ # Use cases for donations
│ │ ├── AddDonationUseCase.ts
│ │ └── GetDonationsUseCase.ts
│ │
│ ├── infrastructure/ # Infrastructure layer
│ │ ├── graphql/ # GraphQL queries and mutations
│ │ ├── lib/ # Zustand store and utility functions
│ │ ├── services/ # Apollo Client configuration
│ │ └── hooks/ # Custom hooks (e.g., use-toast)
│ │
│ ├── presentation/ # Presentation layer (UI)
│ │ ├── components/ # Reusable and feature-specific components
│ │ └── pages/ # Next.js pages
│ │
│ ├── styles/ # Global styles (TailwindCSS)
│ └── next.config.js # Next.js configuration
└── README.md # Project documentation
-
Clone the repository:
git clone https://github.com/yourusername/charity-pwa.git cd charity-pwa
-
Install dependencies:
npm install
-
Run the development server:
npm run dev
The project is divided into four main layers:
-
Domain Layer:
- Contains core business logic such as entities (
Donation
,Metric
), enums, and interfaces.
- Contains core business logic such as entities (
-
Application Layer:
- Use cases encapsulate application-specific actions, like
AddDonationUseCase
andGetDonationsUseCase
.
- Use cases encapsulate application-specific actions, like
-
Infrastructure Layer:
- Handles external integrations:
- GraphQL queries and mutations with Apollo Client.
- Zustand for global state management.
- Custom hooks and utility functions.
- Handles external integrations:
-
Presentation Layer:
- Contains the React components and Next.js pages.
- Focuses on UI rendering using TailwindCSS for modern styling.
Global state management is implemented using Zustand for simplicity and flexibility.
Example of the Donation Store:
import { create } from "zustand";
import { GetDonationsUseCase } from "../../application/donation/GetDonationsUseCase";
import { AddDonationUseCase } from "../../application/donation/AddDonationUseCase";
import { Donation } from "../../domain/entities/Donation";
interface DonationStore {
data: { donations: Donation[]; metrics: any[] };
fetchDonations: () => Promise<void>;
addDonation: (donation: Omit<Donation, "id" | "month">) => Promise<void>;
}
const getDonationsUseCase = new GetDonationsUseCase();
const addDonationUseCase = new AddDonationUseCase();
export const useDonationStore = create<DonationStore>((set) => ({
data: { donations: [], metrics: [] },
fetchDonations: async () => {
const result = await getDonationsUseCase.execute();
set(() => ({ data: result }));
},
addDonation: async (donation) => {
const addedDonation = await addDonationUseCase.execute(donation);
set((state) => ({
data: {
...state.data,
donations: [...state.data.donations, addedDonation],
},
}));
},
}));
GraphQL queries and mutations are defined in the infrastructure layer.
import { gql } from "@apollo/client";
export const GET_DONATIONS = gql`
query GetDonations {
donations {
id
amount
donorName
month
}
}
`;
export const ADD_DONATION = gql`
mutation AddDonation(
$amount: Float!
$donorName: String!
$month: String!
$category: String!
) {
addDonation(
amount: $amount
donorName: $donorName
month: $month
category: $category
) {
id
amount
donorName
month
category
}
}
`;
Given more time, the following features could be added:
- Authentication: User login and role-based access control.
- Advanced Analytics: Filters and interactive charts for donation insights.
- Pagination: Server-side pagination for handling large datasets efficiently.
- Offline Functionality: Enhance PWA capabilities by caching donations locally.
- Localization: Support for multiple languages and regional settings.
- Dark Mode: Implement a theme switcher for light and dark modes.
- Testing: Add unit tests with Jest and end-to-end testing with Cypress.