Skip to content

Commit

Permalink
Integrate admin sr dashboard (#136)
Browse files Browse the repository at this point in the history
* feat: create use-pagination hook

* feat: add pagination to FE

* feat: use real pagination data

* feat: add ErrPaginationParamsError

* chore: remove TODO

* chore: update bruno

* refactor: add type to state

* feat: add params as query keys

* feat: add pagination state to react table hook

* chore: remove commented code

* feat: add page count

* fix: update prev button icon

* feat: remove hide option from table header

* feat: integrate get service request for admin api

* refactor: extract user info state management into a hook

* feat: extract created by info into component

* feat: add created by component to admin sr dashboard column

* feat: integrate server side pagination for admin sr dashboard

* feat: add page params to get admin sr api

---------

Co-authored-by: Joshua Tan <[email protected]>
  • Loading branch information
Ziyang-98 and joshtyf authored May 15, 2024
1 parent ae6d26c commit a22f60b
Show file tree
Hide file tree
Showing 10 changed files with 132 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ meta {
}

get {
url: {{HOST}}/service_request/admin?org_id=1
url: {{HOST}}/service_request/admin?org_id=1&page=1&page_size=1
body: none
auth: inherit
}

query {
org_id: 1
page: 1
page_size: 1
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { toast } from "@/components/ui/use-toast"
import useOrganizationId from "@/hooks/use-organization-id"
import { getAllServiceRequestForAdmin } from "@/lib/service"
import { FormFieldType, JsonFormComponents } from "@/types/json-form-components"
import { StepStatus } from "@/types/pipeline"
import { ServiceRequest, ServiceRequestStatus } from "@/types/service-request"
import { useQuery } from "@tanstack/react-query"
import { useMemo } from "react"

const DUMMY_PIPELINE_FORM: JsonFormComponents = {
fields: [
Expand Down Expand Up @@ -216,8 +221,42 @@ const DUMMY_SERVICE_REQUESTS: ServiceRequest[] = [
},
]

const useOrgServiceRequests = () => {
return { serviceRequests: DUMMY_SERVICE_REQUESTS }
interface UseOrgServiceRequestsOptions {
page: number
pageSize: number
}

const useOrgServiceRequests = ({
page,
pageSize,
}: UseOrgServiceRequestsOptions) => {
const { organizationId } = useOrganizationId()
const { isLoading, data } = useQuery({
queryKey: ["org_service_requests", organizationId, page, pageSize],
queryFn: () =>
getAllServiceRequestForAdmin(organizationId, page, pageSize).catch(
(err) => {
console.error(err)
toast({
title: "Fetching Service Requests Error",
description:
"Failed to fetch Service Requests for organization. Please try again later.",
variant: "destructive",
})
}
),
refetchInterval: 2000,
})

const noOfPages = useMemo(
() =>
data?.metadata.total_count
? Math.ceil(data?.metadata.total_count / pageSize)
: undefined,
[data, pageSize]
)

return { orgServiceRequestsData: data, noOfPages }
}

export default useOrgServiceRequests
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import AdminServiceRequestActions from "./_components/admin-service-request-acti
import { ServiceRequestStatusBadge } from "@/components/layouts/service-request-status-badge"
import { ExternalLink } from "lucide-react"
import { DataTableColumnHeaderFilterableValue } from "@/components/data-table/data-table-column-header-filterable-value"
import CreatedByInfo from "@/components/layouts/created-by-info"

export const orgServiceRequestColumns: ColumnDef<ServiceRequest>[] = [
{
Expand Down Expand Up @@ -57,8 +58,12 @@ export const orgServiceRequestColumns: ColumnDef<ServiceRequest>[] = [
},
},
{
accessorKey: "created_by",
header: "Created By",
cell: ({ row }) => {
const serviceRequest: ServiceRequest = row.original
const userId: string = serviceRequest.user_id
return <CreatedByInfo userId={userId} />
},
},
{
accessorKey: "last_updated",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,14 @@ import HeaderAccessory from "@/components/ui/header-accessory"
import useOrgServiceRequests from "./_hooks/use-org-service-requests"
import { orgServiceRequestColumns } from "./columns"
import { DataTable } from "@/components/data-table/data-table"
import { usePagination } from "@/hooks/use-pagination"

export default function ApproveServiceRequestPage() {
const { serviceRequests } = useOrgServiceRequests()
const { onPaginationChange, pagination } = usePagination()
const { orgServiceRequestsData, noOfPages } = useOrgServiceRequests({
page: pagination.pageIndex + 1, // API is 1-based
pageSize: pagination.pageSize,
})
return (
<div className="flex flex-col justify-start py-10">
<HeaderAccessory />
Expand All @@ -16,7 +21,13 @@ export default function ApproveServiceRequestPage() {
</p>
</div>
<div className="py-10">
<DataTable columns={orgServiceRequestColumns} data={serviceRequests} />
<DataTable
columns={orgServiceRequestColumns}
data={orgServiceRequestsData?.data}
pageCount={noOfPages}
onPaginationChange={onPaginationChange}
pagination={pagination}
/>
</div>
</div>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,6 @@ export function DataTableColumnHeaderFilterableValue<TData, TValue>({
</DropdownMenuRadioItem>
))}
</DropdownMenuRadioGroup>
<DropdownMenuSeparator />
<DropdownMenuItem onClick={() => column.toggleVisibility(false)}>
<EyeOff className="mr-2 h-3.5 w-3.5 text-muted-foreground/70" />
Hide
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/data-table/data-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ import { useMemo, useState } from "react"
interface DataTableProps<TData, TValue> {
columns: ColumnDef<TData, TValue>[]
data?: TData[] | void
onPaginationChange?: (pagination: Updater<PaginationState>) => void
pagination?: PaginationState
onPaginationChange: (pagination: Updater<PaginationState>) => void
pagination: PaginationState
pageCount?: number
}

Expand Down
16 changes: 16 additions & 0 deletions frontend/src/components/layouts/created-by-info.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Skeleton } from "@/components/ui/skeleton"
import useUserInfo from "@/hooks/use-user-info"

interface CreatedByInfoProps {
userId: string
}

export default function CreatedByInfo({ userId }: CreatedByInfoProps) {
const { user, isUserInfoLoading } = useUserInfo(userId)

return isUserInfoLoading ? (
<Skeleton className="w-28 h-5" />
) : (
<p>{user?.name ?? "N.A."}</p>
)
}
19 changes: 3 additions & 16 deletions frontend/src/components/layouts/service-request-details-dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,30 +22,17 @@ import { ExternalLink } from "lucide-react"
import Link from "next/link"
import { useEffect, useState } from "react"
import PipelineStepper from "./pipeline-stepper"
import useUserInfo from "@/hooks/use-user-info"
import CreatedByInfo from "./created-by-info"

interface ServiceRequestDetailsProps {
serviceRequest: ServiceRequest
}

function ServiceRequestDetails({ serviceRequest }: ServiceRequestDetailsProps) {
const [user, setUser] = useState<UserInfo>()
useEffect(() => {
getUserById(serviceRequest.user_id)
.then((user) => setUser(user))
.catch((err) => {
console.error(err)
toast({
title: "Fetching Service Requests Error",
description:
"Failed to fetch Service Requests for user. Please try again later.",
variant: "destructive",
})
})
}, [serviceRequest.user_id])
const {
id: serviceRequestId,
pipeline_version: pipelineVersion,
created_by: createdBy = "",
created_on: createdOn = "",
last_updated: lastUpdated = "",
remarks,
Expand Down Expand Up @@ -84,7 +71,7 @@ function ServiceRequestDetails({ serviceRequest }: ServiceRequestDetailsProps) {
</div>
<div>
<Label className="text-muted-foreground">Created By</Label>
{user ? <p>{user.name}</p> : <Skeleton className="w-28 h-5" />}
<CreatedByInfo userId={serviceRequest.user_id} />
</div>
{steps.some((step) => step.name === "Approval") && (
<div>
Expand Down
27 changes: 27 additions & 0 deletions frontend/src/hooks/use-user-info.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { toast } from "@/components/ui/use-toast"
import { getUserById } from "@/lib/service"
import { UserInfo } from "@/types/user-profile"
import { useEffect, useState } from "react"

const useUserInfo = (userId: string) => {
const [user, setUser] = useState<UserInfo>()
const [isLoading, setIsLoading] = useState(true)
useEffect(() => {
setIsLoading(true)
getUserById(userId)
.then((user) => setUser(user))
.catch((err) => {
console.error(err)
toast({
title: "Fetching User Info Error",
description: "Failed to fetch user info. Please try again later.",
variant: "destructive",
})
})
.finally(() => setIsLoading(false))
}, [userId])

return { user, isUserInfoLoading: isLoading }
}

export default useUserInfo
21 changes: 21 additions & 0 deletions frontend/src/lib/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,27 @@ export async function getAllServiceRequest(
.then((res) => res.data)
}

export async function getAllServiceRequestForAdmin(
organizationId: number,
page?: number,
pageSize?: number
): Promise<{
data: ServiceRequest[]
metadata: {
total_count: number
}
}> {
return apiClient
.get("/service_request/admin", {
params: {
org_id: organizationId,
page: page ?? 1,
page_size: pageSize ?? 10,
},
})
.then((res) => res.data)
}

export async function getServiceRequest(
serviceRequestId: string
): Promise<ServiceRequest> {
Expand Down

0 comments on commit a22f60b

Please sign in to comment.