# DHIS2 custom app

**URL:** <https://community.dhis2.org/t/dhis2-custom-app/62348>\
**Category:** App Development\
**Tags:** maps\
**Created:** [19 November 2024 13:41 UTC](https://community.dhis2.org/t/dhis2-custom-app/62348 "2024-11-19T13:41:58Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Waheed](https://dhis2.b-cdn.net/user_avatar/community.dhis2.org/waheed/32/44440_2.png) [@Waheed](https://community.dhis2.org/u/Waheed)\
**Post date:** [19 November 2024 13:41 UTC](https://community.dhis2.org/t/dhis2-custom-app/62348/1 "2024-11-19T13:41:58Z")

</div>

Hello team,

I am working on querying user data within DHIS2 using React. I was able to successfully fetch the user’s First Name, Username, Last Login, and Email. However, when it comes to fetching the Organization Unit, I am receiving empty values (i.e., `,,`).

Could you help me identify what might be causing this issue? Below is the relevant code:  
import React, { useState } from ‘react’;  
import ‘./UserTable.css’;  
import { useDataQuery } from ‘@dhis2/app-runtime’;

// Define the query to fetch necessary user data  
const myQuery = {  
results: {  
resource: ‘users’,  
params: {  
pageSize: 2500, // Fetch 2500 users per request (adjust according to your system’s limit)  
fields: [  
‘id’,  
‘firstName’,  
‘email’,  
‘username’,  
‘displayName’,  
‘lastLogin’,  
‘organisationUnits’  
],  
},  
},  
};

const UserTable = () =\> {  
const { loading, error, data } = useDataQuery(myQuery);

```
const [currentPage, setCurrentPage] = useState(1);
const [usersPerPage] = useState(20); // Number of users per page
const [searchQuery, setSearchQuery] = useState('');
const [selectedUser, setSelectedUser] = useState(null); // State for selected user
const [isEditing, setIsEditing] = useState(false); // State to toggle edit mode
const [editedUser, setEditedUser] = useState(null); // State for editing user

if (error) {
    return <span>ERROR: {error.message}</span>;
}

if (loading) {
    return <span>Loading...</span>;
}

// Extract users from the API response
const users = data.results.users || [];

// Filter users based on search query
const filteredUsers = users.filter((user) => {
    const query = searchQuery.toLowerCase();
    return (
        (user.displayName && user.displayName.toLowerCase().includes(query)) ||
        (user.firstName && user.firstName.toLowerCase().includes(query)) ||
        (user.email && user.email.toLowerCase().includes(query)) ||
        (user.username && user.username.toLowerCase().includes(query))
    );
});

// Pagination calculation
const totalUsers = filteredUsers.length;
const totalPages = Math.ceil(totalUsers / usersPerPage);
const indexOfLastUser = currentPage * usersPerPage;
const indexOfFirstUser = indexOfLastUser - usersPerPage;
const currentUsers = filteredUsers.slice(indexOfFirstUser, indexOfLastUser);

// Handle page change
const handlePageChange = (pageNumber) => {
    setCurrentPage(pageNumber);
};

// Handle search input change
const handleSearchChange = (event) => {
    setSearchQuery(event.target.value);
};

// Handle user selection
const handleSelectUser = (user) => {
    setSelectedUser(user);
    setEditedUser(user); // Set the selected user as the one to be edited
    setIsEditing(false); // By default, don't start editing
};

// Handle edit toggle
const handleEditToggle = () => {
    setIsEditing(!isEditing);
};

// Handle change in edited fields
const handleInputChange = (event) => {
    const { name, value } = event.target;
    setEditedUser((prev) => ({
        ...prev,
        [name]: value,
    }));
};

// Convert data to CSV
const convertToCSV = (data) => {
    const header = ['Display Name', 'First Name', 'Username', 'Email', 'Last Login','orgUnit','Organisation Units'];
    const rows = data.map((user) => [
        user.displayName || 'N/A',
        user.firstName || 'N/A',
        user.username || 'N/A',
        user.email || 'N/A',
        user.lastLogin || 'N/A',
        user.organisationUnits?.map(unit => unit.name).join(', ') || 'N/A',
    ]);
    const csvContent = [
        header.join(','), // Add header row
        ...rows.map(row => row.join(',')), // Add data rows
    ].join('\n');
    return csvContent;
};

// Handle CSV download
const downloadCSV = () => {
    const csvContent = convertToCSV(filteredUsers);
    const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
    const link = document.createElement('a');
    link.href = URL.createObjectURL(blob);
    link.download = 'users.csv';
    link.click();
};

return (
    <div>
        <h1>User List</h1>

        <div className="search-download-container">
            <input
                type="text"
                placeholder="Search users (name, email)"
                value={searchQuery}
                onChange={handleSearchChange}
                className="search-input"
            />
            <button onClick={downloadCSV} className="download-button">
                Download as CSV
            </button>
        </div>

        <table className="user-table">
            <thead>
                <tr>
                    <th>Display Name</th>
                    <th>First Name</th>
                    <th>Username</th>
                    <th>Last Login</th>
                    <th>Email</th>
                    <th>Organisation Units</th>
                </tr>
            </thead>
            <tbody>
                {currentUsers.map(user => (
                    <tr key={user.id} onClick={() => handleSelectUser(user)}>
                        <td>{user.displayName || 'N/A'}</td>
                        <td>{user.firstName || 'N/A'}</td>
                        <td>{user.username || 'N/A'}</td>
                        <td>{user.lastLogin || 'N/A'}</td>
                        <td>{user.email || 'N/A'}</td>
                        <td>
                            {user.organisationUnits?.map(unit => unit.name).join(', ') || 'N/A'}
                        </td>
                    </tr>
                ))}
            </tbody>
        </table>

        {selectedUser && (
            <div className="user-details">
                <h2>User Details</h2>
                {isEditing ? (
                    <div className="edit-form">
                        <label>
                            Display Name:
                            <input
                                type="text"
                                name="displayName"
                                value={editedUser.displayName}
                                onChange={handleInputChange}
                            />
                        </label>
                        <label>
                            First Name:
                            <input
                                type="text"
                                name="firstName"
                                value={editedUser.firstName}
                                onChange={handleInputChange}
                            />
                        </label>
                        <label>
                            Email:
                            <input
                                type="email"
                                name="email"
                                value={editedUser.email}
                                onChange={handleInputChange}
                            />
                        </label>
                        <label>
                            Username:
                            <input
                                type="text"
                                name="username"
                                value={editedUser.username}
                                onChange={handleInputChange}
                            />
                        </label>
                        <button onClick={handleEditToggle}>Save Changes</button>
                    </div>
                ) : (
                    <div>
                        <p><strong>Display Name:</strong> {selectedUser.displayName}</p>
                        <p><strong>First Name:</strong> {selectedUser.firstName}</p>
                        <p><strong>Email:</strong> {selectedUser.email}</p>
                        <p><strong>Username:</strong> {selectedUser.username}</p>
                        <p><strong>Last Login:</strong> {selectedUser.lastLogin}</p>
                        <p><strong>Organisation Units:</strong> {selectedUser.organisationUnits?.map(unit => unit.name).join(', ')}</p>
                        <button onClick={handleEditToggle}>Edit User</button>
                    </div>
                )}
            </div>
        )}

        <div className="pagination">
            <button onClick={() => handlePageChange(1)} disabled={currentPage === 1}>First</button>
            <button onClick={() => handlePageChange(currentPage - 1)} disabled={currentPage === 1}>Previous</button>
            <span>Page {currentPage} of {totalPages}</span>
            <button onClick={() => handlePageChange(currentPage + 1)} disabled={currentPage === totalPages}>Next</button>
            <button onClick={() => handlePageChange(totalPages)} disabled={currentPage === totalPages}>Last</button>
        </div>
    </div>
);

```

};

export default UserTable;

the output is

 ![Screenshot from 2024-11-19 15-34-21](https://dhis2.b-cdn.net/uploads/default/original/3X/3/4/348299d1019b5914ee04ea768072a5d9dcfca448.png)

Thank you for your assistance!

Best regards,

---

<div class="post-metadata">

**Author:** ![SouthSudan](https://dhis2.b-cdn.net/user_avatar/community.dhis2.org/southsudan/32/42690_2.png) [@SouthSudan](https://community.dhis2.org/u/SouthSudan)\
**Post date:** [19 November 2024 15:12 UTC](https://community.dhis2.org/t/dhis2-custom-app/62348/2 "2024-11-19T15:12:49Z")

</div>

**Suggested Modification to Query**

Dear @Waheed , Greetings

I hope this message finds you well.

Please make the following adjustment to the code, and it should work as expected:

javascript

Copy code

```auto
resource: 'users',
params: {
    pageSize: 2500, // Fetch 2500 users per request (adjust according to your system's limit)
    fields: [
        'id', 
        'firstName', 
        'email', 
        'username', 
        'displayName', 
        'lastLogin', 
        'organisationUnits[id,name]' // Request specific fields for organisation units
    ],
},

```

This modification ensures that the necessary fields for the organization units are correctly included in the response.

Let me know if you need any further assistance.

Best regards,

---

<div class="post-metadata">

**Author:** ![Waheed](https://dhis2.b-cdn.net/user_avatar/community.dhis2.org/waheed/32/44440_2.png) [@Waheed](https://community.dhis2.org/u/Waheed)\
**Post date:** [19 November 2024 15:18 UTC](https://community.dhis2.org/t/dhis2-custom-app/62348/3 "2024-11-19T15:18:45Z")

</div>

Thanks a lot @SouthSudan

 ![Screenshot from 2024-11-19 17-22-07](https://dhis2.b-cdn.net/uploads/default/original/3X/9/4/94df7568bdc6086feb3801a69f390d8a38642201.png)  
Best Regards
