Source

components/memos/MemosPage.jsx

import React, { useEffect, useState } from 'react';
import { useAuth } from '../../hooks/useAuth';
import { useNavigate } from 'react-router-dom';
import { Plus } from 'lucide-react'; // Import Plus icon for the create button
import Modal from '../ui/Modal';
import MemoTabbedList from '../prototype/MemoTabbedList';
import toast from 'react-hot-toast';
import MemoForm from './MemoForm';

/**
 * MemosPage Component
 *
 * This component displays a list of memos for the current user within a specific hospital context.
 * It fetches memos upon loading, allows memo creators to initiate the creation of new memos via a modal,
 * and provides navigation to individual memo detail pages.
 *
 * It utilizes `useAuth` for accessing user information, API services, and hospital context,
 * `useNavigate` for routing, and various state variables to manage loading states, memo data,
 * and modal visibility.
 */
const MemosPage = () => {
  // Fetch user, API service, and hospital context from the authentication hook
  const { user, apiService, hospital } = useAuth();
  const hospitalId = hospital?.id || localStorage.getItem('hospitalId');
  const navigate = useNavigate();


  const [memos, setMemos] = useState([]);
  const [loading, setLoading] = useState(true);
  const [createOpen, setCreateOpen] = useState(false);

  const isCreator = user?.is_creator;

  useEffect(() => {
    /**
 * Asynchronously loads the memos for the current user and hospital.
 * Sets the fetched memos into the `memos` state, handles loading state,
 * and displays error messages using `react-hot-toast` if the fetch fails.
 */
    const loadMemos = async () => {
      try {
        // Fetch memos from the API service
        const data = await apiService.getUserMemos(hospitalId);
        // Log the fetched data for debugging
        console.log(data);  
        setMemos(data);
      } catch (err) {
        console.error(err);
        toast.error(err.message);
      } finally {
        setLoading(false);
      }
    };
    loadMemos();
  }, [apiService, hospitalId]);

  /**
 * Handles the click event on a memo row.
 * Navigates the user to the detail page for the clicked memo.
 *
 * @param {object} memo - The memo object that was clicked.
 * @param {string} memo.memoId - The unique identifier of the memo.
 */
  const handleRowClick = (memo) => {
    navigate(`/memo/${memo.memoId}`);
  };

  /**
 * Handles the successful creation of a new memo.
 * Closes the memo creation modal and navigates to the newly created memo's detail page.
 *
 * @param {string} memoId - The unique identifier of the newly created memo.
 */
  const handleCreateSuccess = (memoId) => {
    setCreateOpen(false);
    navigate(`/memo/${memoId}`);
  };

  // Helper function to format date strings (currently not used in the rendered JSX)
  const formatDate = (dateString) => {
    // Create a new Date object from the input string
    const date = new Date(dateString);
    return date.toLocaleDateString('en-US', {
      month: 'short',
      day: 'numeric',
      hour: '2-digit',
      minute: '2-digit'
    });
  };

  // Helper function to determine status color based on tagged role (currently not used in the rendered JSX)
  const getStatusColor = (taggedRoleName) => {
    // You can customize this based on your business logic
    const colors = {
      'nursing superintendent': 'bg-blue-100 text-blue-800',
      'doctor': 'bg-green-100 text-green-800',
      'admin': 'bg-purple-100 text-purple-800',
      'default': 'bg-gray-100 text-gray-800'
    };
    return colors[taggedRoleName?.toLowerCase()] || colors.default;
  };

  return (
    // Main container with minimal height and background color
    <div className="min-h-screen bg-gray-50">
      {/* Header */}
      <div className="bg-white shadow-sm border-b sticky top-0 z-10">
        <div className="px-4 py-4">
          <div className="flex justify-between items-center">
            <div>
              <h1 className="text-xl font-bold text-gray-900">Memos</h1>
              <p className="text-sm text-gray-500 mt-1">{memos.length} active memos</p>
            </div>
            {/* Show the Create button only if the user is a creator */}
            {isCreator && (
              <button
                onClick={() => setCreateOpen(true)}
                className="bg-blue-600 text-white px-4 py-2 rounded-lg text-sm font-medium hover:bg-blue-700 transition-colors flex items-center gap-2 shadow-sm"
              >
                <Plus className="w-4 h-4" />
                Create
              </button>
            )}
          </div>
        </div>
      </div>

      {/* Content */}
      <div className="px-4 py-4">
        {loading ? (
          // Display a loading spinner while fetching memos
          <div className="flex justify-center items-center py-12">
            <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"></div>
          </div>
        ) : memos.length === 0 ? (
          // Display a message when no memos are found
          <div className="text-center py-12">
            <div className="text-gray-400 text-4xl mb-4">📝</div>
            <p className="text-gray-500 text-lg">No memos found</p>
            <p className="text-gray-400 text-sm mt-2">Create your first memo to get started</p>
          </div>
        ) : (
          <MemoTabbedList data={memos} onMemoClick={handleRowClick} />
        )}
      </div>

      {/* Modal for creating a new memo */}
      <Modal
        isOpen={createOpen}
        onClose={() => setCreateOpen(false)}
        title="Create Memo"
        size="md"
      >
        <MemoForm
          onSuccess={handleCreateSuccess}
          onCancel={() => setCreateOpen(false)}
        />
      </Modal>
    </div>
  );

  // Note: formatDate and getStatusColor are defined but not currently used in the rendered JSX.
  // They might be intended for future use within the MemoTabbedList or memo detail views.
};

export default MemosPage;