Skip to content

Refactor Backend API Calling Stack(TBD) #7

@A-lexisL

Description

@A-lexisL

Current Backend API Calling Stack

Frontend Structure (high-level)

  • src/main.js: Vue app bootstrap + router.
  • src/views/: page-level views (e.g. Home.vue, Login.vue, CourseDetail.vue).
  • src/components/: reusable UI components.
  • src/composables/: reusable state/data hooks (e.g. useAuth, useCourses, useReviews).
  • src/utils/: small utilities (cookies, auth flow helpers, sanitization).

Where API calls currently live

There is no single centralized API client; calls are spread across:

  • src/utils/auth.js (auth endpoints)
  • src/utils/api.js (auth status check)
  • src/composables/useCourses.js (course list + departments)
  • src/composables/useReviews.js (review CRUD + voting)
  • src/views/Home.vue (landing stats)
  • src/views/CourseDetail.vue (course detail fetch)
  • src/views/CourseReviewSearch.vue (review search fetch)
  • src/composables/useAuth.js (logout)

The New Architecture Overview (Layered)

  1. src/api/client.js (The Engine): Centralized Axios instance with interceptors (Base URL, Auth headers).
  2. src/api/modules/*.js (The Order Desk): Pure functions that define specific endpoint paths (No logic, just URLs).
  3. src/composables/use*.js (The Waiter): Manages reactive state (loading, data, error) and calls the API modules.
  4. src/views/*.vue (The Diner): The UI that just displays data and triggers actions.

Step 1: The Base Client (src/api/client.js)

Centralize your Axios logic here.

// src/api/client.js
import axios from 'axios';

const apiClient = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL, // Use the env variable we discussed!
  timeout: 10000,
  headers: { 'Content-Type': 'application/json' }
});

// Request Interceptor: Automatically attach Token to every request

// Response Interceptor: Global Error Handling (e.g., **redirect to login on 401 and 403**)

export default apiClient;

Step 2: API Modules (src/api/modules/)

Group your endpoints by domain. This replaces the messy utils/api.js.

src/api/modules/courses.js

export const getCourseDetail = (id) => {
  return apiClient.get(`/courses/${id}/`);
};

src/api/modules/auth.js

export const login = (credentials) => {
  return apiClient.post('/auth/login/', credentials);
};

Step 3: Composables (src/composables/)

Keep your UI clean by putting data-fetching logic here.

src/composables/useCourses.js

import { ref } from 'vue';
import { getCourses } from '@/api/modules/courses';

export function useCourses() {
  const courses = ref([]);
  const isLoading = ref(false);
  const error = ref(null);

  const fetchCourses = async (searchParams) => {
    isLoading.value = true;
    try {
      const response = await getCourses(searchParams);
      courses.value = response.data;
    } catch (err) {
      error.value = err.message;
    } finally {
      isLoading.value = false;
    }
  };

  return { courses, isLoading, error, fetchCourses };
}

Step 4: The View Layer (src/views/Home.vue)

The view now knows nothing about Axios or URLs. It only knows about the Composable.

<script setup>
const { courses, isLoading, error, fetchCourses } = useCourses();

onMounted(() => {
  fetchCourses(); // Just call the function!
});
</script>

Summary of the "Clean" Directory Structure

src/
|-- api/                <-- NEW: API Central Command
|   |-- client.js       <-- Axios Instance + Interceptors
|   |-- modules/        <-- Endpoint definitions
|       |-- auth.js     <-- login, verifyCaptcha
|       |-- courses.js  <-- list, detail
|       |-- reviews.js  <-- CRUD
|-- composables/        <-- Logic & State
|   |-- useAuth.js      <-- uses api/modules/auth.js
|   |-- useCourses.js   <-- uses api/modules/courses.js
|-- views/              <-- UI Pages
|   |-- Home.vue        <-- uses useCourses.js

Why this fixes your problems:

  1. Centralized Auth: Token injection happens in client.js once. No more manual headers in useCourses.js.
  2. No Duplicate Calls: If CourseDetail.vue and useReviews.js both need course data, they call the same api/modules/courses.js.
  3. Environment Agnostic: If your backend URL changes, you change exactly one line in .env.
  4. Testable: You can test api/modules/courses.js without even running the Vue UI.
  5. Base Interceptor: handle header, error handling easily

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requesthelp wantedExtra attention is needed

    Projects

    Status

    In Progress

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions