-
Notifications
You must be signed in to change notification settings - Fork 0
Frontend Development Documentation
This document outlines how to structure and build the Schooltracker frontend. Follow these guidelines to ensure consistency across components, routes, API calls, and utility functions.
Organize the frontend code in a clear, modular manner. Below is a recommended folder structure:
frontend/
├── public/
├── src/
│ ├── api/ # API call functions and related logic
│ ├── components/ # Reusable UI components
│ │ └── SomeComponent/
│ │ ├── SomeComponent.tsx
│ │ └── props.ts # Component props and types
│ ├── constants/ # All constants (routes, endpoints, etc.)
│ │ ├── Routes.ts # Application route constants
│ │ └── Endpoints.ts # API endpoints constants
│ ├── interfaces/ # General interface files (e.g., modal interfaces)
│ │ └── ModalProps.ts # Modal-specific types
│ ├── contexts/ # Global state contexts
│ ├── hooks/ # Custom hooks
│ ├── pages/ # Page-level components
│ ├── utilities/ # Utility functions (formatters, helpers, etc.)
│ ├── App.tsx
│ ├── main.tsx
│ └── index.css
├── .env
├── package.json
└── tsconfig.json
All routes must be centralized in the constants/Routes.ts file. This file will contain a single exported object that holds all the paths for the application.
/**
* This file contains constants for all of the routes in the app
*/
export const ROUTES = {
App: {
main: "/",
},
Home: {
main: "/home",
},
Dashboard: {
main: "/dashboard",
},
// Add additional routes here...
};Use these route constants throughout your application when defining React Router paths and linking between pages.
Store all API endpoint constants in a single file: constants/Endpoints.ts. This file should define base URLs using environment variables and create a structured object for each feature’s endpoints.
const BASE_URL = import.meta.env.VITE_BASE_URL;
const AUTH_URL = import.meta.env.VITE_BASE_AUTH_URL;
const endpoints = {
Auth: {
getLoginOtp: AUTH_URL + "/auth/login/otp",
verifyOtp: AUTH_URL + "/auth/verify/otp",
getRegisterOtp: AUTH_URL + "/auth/register/otp",
},
SchoolTrackerUser: {
main: BASE_URL + "/schooltracker/users",
getApplications: BASE_URL + "/schooltracker/users/applications",
},
// Add more endpoint groups as needed...
};
export { endpoints, BASE_URL };All API call functions should be encapsulated in files located in the api/ directory. For example, you might have files like api/auth.ts or api/schoolTracker.ts that import the relevant endpoints from the constants file and use Axios (or another HTTP client) to perform calls.
import axios from 'axios';
import { endpoints } from '../constants/Endpoints';
export const sendLoginOtp = async (email: string) => {
try {
const response = await axios.post(endpoints.Auth.getLoginOtp, { email });
return response.data;
} catch (error) {
throw error;
}
};
// Additional API functions for auth...This approach keeps all API interactions centralized and easier to maintain.
For each React component, define its props and types in a separate props.ts file located within the component's directory. This ensures that the component’s API is clearly documented and maintainable.
export interface SomeComponentProps {
title: string;
onClick: () => void;
// Add additional props as needed...
}Then import these types in your component file:
// src/components/SomeComponent/SomeComponent.tsx
import React from 'react';
import { SomeComponentProps } from './props';
const SomeComponent: React.FC<SomeComponentProps> = ({ title, onClick }) => {
return (
<div onClick={onClick}>
<h1>{title}</h1>
</div>
);
};
export default SomeComponent;For interfaces that are shared across multiple components—such as modal properties—create a separate file in the interfaces/ directory.
export interface ModalProps {
isOpen: boolean;
title?: string;
content: React.ReactNode;
onClose: () => void;
}Components that use modals can import these shared types to ensure consistency.
General utility functions and helper methods should be placed in the utilities/ directory. These might include formatting functions, date manipulation utilities, or other reusable logic.
export const formatDate = (dateString: string): string => {
const options: Intl.DateTimeFormatOptions = { year: 'numeric', month: 'long', day: 'numeric' };
return new Date(dateString).toLocaleDateString(undefined, options);
};Any constant values that do not fit into routes or endpoints should also be stored in the constants/ directory.
-
Consistency: Always use the constants from
Routes.tsandEndpoints.tsto avoid hardcoding URLs or paths across your project. - Separation of Concerns: Keep API calls, component logic, types, and utilities in their respective directories to maintain a modular and scalable codebase.
- Documentation: Comment your code you build. This ensures team members can quickly understand the structure.