primereact icon indicating copy to clipboard operation
primereact copied to clipboard

Virtual scroll bar not working as expected

Open bloodykheeng opened this issue 2 months ago • 1 comments

The virtiual scroll bar is failing to adopt to my styles its only working when i apply card if i dont put class card it gets hidden i se nothing rendered

 // <div className="flex-1 overflow-hidden">
                        <div className="card flex justify-content-center">
                            <VirtualScroller
                                items={agentsData}
                                itemSize={80}
                                itemTemplate={agentItemTemplate}
                            // className="h-full"
                            // style={{ height: '100%' }}
                            // className="border-1 surface-border border-round"
                            // style={{ width: '200px', height: '200px' }}
                            />
                        </div>

here is my full code

'use client'

import React, { useState } from "react";
import { Card } from "primereact/card";
import { Button } from "primereact/button";
import { InputText } from "primereact/inputtext";
import { VirtualScroller, VirtualScrollerTemplateOptions } from 'primereact/virtualscroller';
import { useInfiniteQuery } from "@tanstack/react-query";
import { ProgressSpinner } from "primereact/progressspinner";

import MaterialUiLoaderLottie from "@/assets/nice-lotties/material-ui-loading-lottie.json";
import SnailErrorLottie from "@/assets/nice-lotties/snail-error-lottie.json";
// import SateLiteLottie from "@/assets/nice-lotties/satelite-loading-lottie.json";
// import FileLoadingLottie from "@/assets/nice-lotties/FileLoadingLottie.json";
import SkeletonLoadingLottie from "@/assets/nice-lotties/SkeletonLoadingLottie.json";
import NoDataLottie from "@/assets/nice-lotties/nodata.json";

import { getAllAgents } from "@/services/agents/agents-service";
import useHandleQueryError from "@/hooks/useHandleQueryError";

import dynamic from "next/dynamic";
const Lottie = dynamic(() => import("lottie-react"), { ssr: false });

interface Agent {
    id: number;
    name: string;
    code?: string;
    email?: string;
    phone?: string;
    status?: string;
    created_at?: string;
}

function UserAgentsListing() {
    const [globalSearch, setGlobalSearch] = useState("");
    const [globalSearchTerm, setGlobalSearchTerm] = useState("");

    // Fetch Agents data using useInfiniteQuery
    const { data, error, fetchNextPage, hasNextPage, isFetching, isFetchingNextPage, status, } = useInfiniteQuery({
        queryKey: ["user-agents", "paginate", globalSearchTerm],
        queryFn: ({ pageParam = 1 }) => getAllAgents({ page: pageParam, search: globalSearchTerm, paginate: true }),
        getNextPageParam: (queryData) => {
            console.log("🚀 ~ UserAgentsListing ~ queryData:", queryData);
            const pageData = queryData?.data?.data;
            return pageData?.current_page < pageData?.last_page ? pageData.current_page + 1 : undefined;
        },
        initialPageParam: 1,
    });


    const isError = status === "error";
    const isPending = status === "pending";

    useHandleQueryError({ isError, error });

    // Flatten the paginated data
    const agentsData = data?.pages?.flatMap(page => page?.data?.data?.data) || [];

    // Search function
    const handleSearch = () => {
        setGlobalSearchTerm(globalSearch);
    };

    // Agent item template for VirtualScroller
    const agentItemTemplate = (agent: Agent, options: VirtualScrollerTemplateOptions) => {
        return (
            <div className="border-b border-gray-200 dark:border-gray-700 p-3 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors">
                <div className="flex items-start justify-between gap-3">
                    <div className="flex-1 min-w-0">
                        <div className="flex items-center gap-2 mb-1">
                            <h4 className="text-sm font-semibold text-gray-800 dark:text-white truncate">
                                {agent.name}
                            </h4>
                            {agent.code && (
                                <span className="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-indigo-100 text-indigo-800 dark:bg-indigo-900 dark:text-indigo-100">
                                    {agent.code}
                                </span>
                            )}
                        </div>

                        {agent.email && (
                            <p className="text-xs text-gray-600 dark:text-gray-400 truncate">
                                📧 {agent.email}
                            </p>
                        )}

                        {agent.phone && (
                            <p className="text-xs text-gray-600 dark:text-gray-400 truncate">
                                📱 {agent.phone}
                            </p>
                        )}
                    </div>

                    {agent.status && (
                        <span className={`inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium flex-shrink-0 ${agent.status === 'active'
                            ? 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-100'
                            : 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-100'
                            }`}>
                            {agent.status}
                        </span>
                    )}
                </div>
            </div>
        );
    };

    return (
        <div className="h-full">
            {isError ? (
                <div className="flex justify-center items-center h-full">
                    <div className="max-w-xs">
                        <Lottie animationData={SnailErrorLottie} loop autoplay />
                    </div>
                </div>
            ) : (
                <div className="h-full flex flex-col">
                    {/* Search Box */}
                    <div className="p-3 border-b border-gray-200 dark:border-gray-700">
                        <div className="p-inputgroup">
                            <InputText
                                type="search"
                                value={globalSearch}
                                onChange={(e) => setGlobalSearch(e.target.value)}
                                placeholder="Search agents by name, code..."
                                className="text-sm"
                            />
                            <Button
                                icon="pi pi-search"
                                className="p-button-primary"
                                onClick={handleSearch}
                                size="small"
                            />
                        </div>
                    </div>

                    {/* Agents List with VirtualScroller */}
                    {agentsData.length === 0 && !isPending ? (
                        <div className="flex justify-center items-center flex-1">
                            <div className="max-w-xs">
                                <Lottie animationData={NoDataLottie} loop autoplay />
                                <p className="text-center text-sm text-gray-600 dark:text-gray-400 mt-2">
                                    No agents assigned
                                </p>
                            </div>
                        </div>
                    ) : (
                        // <div className="flex-1 overflow-hidden">
                        <div className="card flex justify-content-center">
                            <VirtualScroller
                                items={agentsData}
                                itemSize={80}
                                itemTemplate={agentItemTemplate}
                                // className="h-full"
                                // style={{ height: '100%' }}
                                className="border-1 surface-border border-round"
                                style={{ width: '200px', height: '200px' }}
                            />
                        </div>
                    )}

                    {/* Loading Spinner */}
                    {isPending && (
                        <div className="flex justify-center items-center p-4 border-t border-gray-200 dark:border-gray-700">
                            <ProgressSpinner style={{ width: "25px", height: "25px" }} />
                            <span className="ml-2 text-sm">Loading agents...</span>
                        </div>
                    )}

                    {/* Load More Button */}
                    {hasNextPage && (
                        <div className="p-3 border-t border-gray-200 dark:border-gray-700">
                            <Button
                                label={isFetchingNextPage ? "Loading more agents..." : "Load More"}
                                className="w-full p-button-outlined p-button-sm"
                                icon={isFetchingNextPage ? "pi pi-spinner pi-spin" : "pi pi-chevron-down"}
                                onClick={() => fetchNextPage()}
                                disabled={isFetchingNextPage}
                                size="small"
                            />
                        </div>
                    )}

                    {!hasNextPage && agentsData.length > 0 && (
                        <div className="p-3 border-t border-gray-200 dark:border-gray-700">
                            <Button
                                label="All agents loaded"
                                className="w-full p-button-secondary p-button-sm"
                                disabled
                                size="small"
                            />
                        </div>
                    )}
                </div>
            )}
        </div>
    );
}

export default UserAgentsListing;

bloodykheeng avatar Nov 06 '25 09:11 bloodykheeng

Actually i dono what but my whole app stopped reflecting changes the moment i imported that virtual scroll bar i had to first stop npm run dev and restart my app and remove it from my project to see ui changes again

bloodykheeng avatar Nov 06 '25 10:11 bloodykheeng