mirror of
https://github.com/formbricks/formbricks.git
synced 2026-03-09 11:19:24 -05:00
Compare commits
2 Commits
4.7.4
...
person-tab
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ec149d7fce | ||
|
|
f5e349a91f |
@@ -1,14 +1,11 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import {
|
import { getPersonsAction } from "@/app/(app)/environments/[environmentId]/(people)/people/actions";
|
||||||
getPersonAttributesAction,
|
|
||||||
getPersonsAction,
|
|
||||||
} from "@/app/(app)/environments/[environmentId]/(people)/people/actions";
|
|
||||||
import { PersonTable } from "@/app/(app)/environments/[environmentId]/(people)/people/components/PersonTable";
|
import { PersonTable } from "@/app/(app)/environments/[environmentId]/(people)/people/components/PersonTable";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { TEnvironment } from "@formbricks/types/environment";
|
import { TEnvironment } from "@formbricks/types/environment";
|
||||||
import { TPerson, TPersonTableData } from "@formbricks/types/people";
|
import { TPersonWithAttributes } from "@formbricks/types/people";
|
||||||
|
|
||||||
interface PersonDataViewProps {
|
interface PersonDataViewProps {
|
||||||
environment: TEnvironment;
|
environment: TEnvironment;
|
||||||
@@ -17,8 +14,7 @@ interface PersonDataViewProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const PersonDataView = ({ environment, personCount, itemsPerPage }: PersonDataViewProps) => {
|
export const PersonDataView = ({ environment, personCount, itemsPerPage }: PersonDataViewProps) => {
|
||||||
const [persons, setPersons] = useState<TPerson[]>([]);
|
const [persons, setPersons] = useState<TPersonWithAttributes[]>([]);
|
||||||
const [personTableData, setPersonTableData] = useState<TPersonTableData[]>([]);
|
|
||||||
const [pageNumber, setPageNumber] = useState<number>(1);
|
const [pageNumber, setPageNumber] = useState<number>(1);
|
||||||
const [totalPersons, setTotalPersons] = useState<number>(0);
|
const [totalPersons, setTotalPersons] = useState<number>(0);
|
||||||
const [isDataLoaded, setIsDataLoaded] = useState<boolean>(false);
|
const [isDataLoaded, setIsDataLoaded] = useState<boolean>(false);
|
||||||
@@ -40,38 +36,13 @@ export const PersonDataView = ({ environment, personCount, itemsPerPage }: Perso
|
|||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching people data:", error);
|
console.error("Error fetching people data:", error);
|
||||||
|
} finally {
|
||||||
|
setIsDataLoaded(true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fetchData();
|
fetchData();
|
||||||
}, [pageNumber]);
|
}, [pageNumber, personCount, itemsPerPage, environment.id]);
|
||||||
|
|
||||||
// Fetch additional person attributes and update table data
|
|
||||||
useEffect(() => {
|
|
||||||
const fetchAttributes = async () => {
|
|
||||||
const updatedPersonTableData = await Promise.all(
|
|
||||||
persons.map(async (person) => {
|
|
||||||
const attributes = await getPersonAttributesAction({
|
|
||||||
environmentId: environment.id,
|
|
||||||
personId: person.id,
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
createdAt: person.createdAt,
|
|
||||||
personId: person.id,
|
|
||||||
userId: person.userId,
|
|
||||||
email: attributes?.data?.email ?? "",
|
|
||||||
attributes: attributes?.data ?? {},
|
|
||||||
};
|
|
||||||
})
|
|
||||||
);
|
|
||||||
setPersonTableData(updatedPersonTableData);
|
|
||||||
setIsDataLoaded(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (persons.length > 0) {
|
|
||||||
fetchAttributes();
|
|
||||||
}
|
|
||||||
}, [persons]);
|
|
||||||
|
|
||||||
const fetchNextPage = async () => {
|
const fetchNextPage = async () => {
|
||||||
if (hasMore && !loadingNextPage) {
|
if (hasMore && !loadingNextPage) {
|
||||||
@@ -91,9 +62,17 @@ export const PersonDataView = ({ environment, personCount, itemsPerPage }: Perso
|
|||||||
};
|
};
|
||||||
|
|
||||||
const deletePersons = (personIds: string[]) => {
|
const deletePersons = (personIds: string[]) => {
|
||||||
setPersons(persons.filter((p) => !personIds.includes(p.id)));
|
setPersons((prevPersons) => prevPersons.filter((p) => !personIds.includes(p.id)));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const personTableData = persons.map((person) => ({
|
||||||
|
createdAt: person.createdAt,
|
||||||
|
personId: person.id,
|
||||||
|
userId: person.userId,
|
||||||
|
email: person.attributes.email,
|
||||||
|
attributes: person.attributes,
|
||||||
|
}));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PersonTable
|
<PersonTable
|
||||||
data={personTableData}
|
data={personTableData}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import { cn } from "@formbricks/lib/cn";
|
|||||||
import { TPersonTableData } from "@formbricks/types/people";
|
import { TPersonTableData } from "@formbricks/types/people";
|
||||||
import { Button } from "@formbricks/ui/Button";
|
import { Button } from "@formbricks/ui/Button";
|
||||||
import { DataTableHeader, DataTableSettingsModal, DataTableToolbar } from "@formbricks/ui/DataTable";
|
import { DataTableHeader, DataTableSettingsModal, DataTableToolbar } from "@formbricks/ui/DataTable";
|
||||||
|
import { getCommonPinningStyles } from "@formbricks/ui/DataTable/lib/utils";
|
||||||
import { Skeleton } from "@formbricks/ui/Skeleton";
|
import { Skeleton } from "@formbricks/ui/Skeleton";
|
||||||
import { Table, TableBody, TableCell, TableHeader, TableRow } from "@formbricks/ui/Table";
|
import { Table, TableBody, TableCell, TableHeader, TableRow } from "@formbricks/ui/Table";
|
||||||
|
|
||||||
@@ -189,6 +190,7 @@ export const PersonTable = ({
|
|||||||
if (cell.column.id === "select") return;
|
if (cell.column.id === "select") return;
|
||||||
router.push(`/environments/${environmentId}/people/${row.id}`);
|
router.push(`/environments/${environmentId}/people/${row.id}`);
|
||||||
}}
|
}}
|
||||||
|
style={cell.column.id === "select" ? getCommonPinningStyles(cell.column) : {}}
|
||||||
className={cn(
|
className={cn(
|
||||||
"border-slate-300 bg-white shadow-none group-hover:bg-slate-100",
|
"border-slate-300 bg-white shadow-none group-hover:bg-slate-100",
|
||||||
row.getIsSelected() && "bg-slate-100",
|
row.getIsSelected() && "bg-slate-100",
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { prisma } from "@formbricks/database";
|
|||||||
import { ZOptionalNumber, ZString } from "@formbricks/types/common";
|
import { ZOptionalNumber, ZString } from "@formbricks/types/common";
|
||||||
import { ZId } from "@formbricks/types/common";
|
import { ZId } from "@formbricks/types/common";
|
||||||
import { DatabaseError, ResourceNotFoundError } from "@formbricks/types/errors";
|
import { DatabaseError, ResourceNotFoundError } from "@formbricks/types/errors";
|
||||||
import { TPerson } from "@formbricks/types/people";
|
import { TPerson, TPersonWithAttributes } from "@formbricks/types/people";
|
||||||
import { cache } from "../cache";
|
import { cache } from "../cache";
|
||||||
import { ITEMS_PER_PAGE } from "../constants";
|
import { ITEMS_PER_PAGE } from "../constants";
|
||||||
import { validateInputs } from "../utils/validate";
|
import { validateInputs } from "../utils/validate";
|
||||||
@@ -17,6 +17,16 @@ export const selectPerson = {
|
|||||||
createdAt: true,
|
createdAt: true,
|
||||||
updatedAt: true,
|
updatedAt: true,
|
||||||
environmentId: true,
|
environmentId: true,
|
||||||
|
attributes: {
|
||||||
|
select: {
|
||||||
|
value: true,
|
||||||
|
attributeClass: {
|
||||||
|
select: {
|
||||||
|
name: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
type TransformPersonInput = {
|
type TransformPersonInput = {
|
||||||
@@ -33,7 +43,7 @@ type TransformPersonInput = {
|
|||||||
updatedAt: Date;
|
updatedAt: Date;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const transformPrismaPerson = (person: TransformPersonInput): TPerson => {
|
export const transformPrismaPerson = (person: TransformPersonInput): TPersonWithAttributes => {
|
||||||
const attributes = person.attributes.reduce(
|
const attributes = person.attributes.reduce(
|
||||||
(acc, attr) => {
|
(acc, attr) => {
|
||||||
acc[attr.attributeClass.name] = attr.value;
|
acc[attr.attributeClass.name] = attr.value;
|
||||||
@@ -49,7 +59,7 @@ export const transformPrismaPerson = (person: TransformPersonInput): TPerson =>
|
|||||||
environmentId: person.environmentId,
|
environmentId: person.environmentId,
|
||||||
createdAt: new Date(person.createdAt),
|
createdAt: new Date(person.createdAt),
|
||||||
updatedAt: new Date(person.updatedAt),
|
updatedAt: new Date(person.updatedAt),
|
||||||
} as TPerson;
|
} as TPersonWithAttributes;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getPerson = reactCache(
|
export const getPerson = reactCache(
|
||||||
@@ -81,13 +91,13 @@ export const getPerson = reactCache(
|
|||||||
);
|
);
|
||||||
|
|
||||||
export const getPeople = reactCache(
|
export const getPeople = reactCache(
|
||||||
(environmentId: string, page?: number): Promise<TPerson[]> =>
|
(environmentId: string, page?: number): Promise<TPersonWithAttributes[]> =>
|
||||||
cache(
|
cache(
|
||||||
async () => {
|
async () => {
|
||||||
validateInputs([environmentId, ZId], [page, ZOptionalNumber]);
|
validateInputs([environmentId, ZId], [page, ZOptionalNumber]);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return await prisma.person.findMany({
|
const persons = await prisma.person.findMany({
|
||||||
where: {
|
where: {
|
||||||
environmentId: environmentId,
|
environmentId: environmentId,
|
||||||
},
|
},
|
||||||
@@ -95,6 +105,8 @@ export const getPeople = reactCache(
|
|||||||
take: page ? ITEMS_PER_PAGE : undefined,
|
take: page ? ITEMS_PER_PAGE : undefined,
|
||||||
skip: page ? ITEMS_PER_PAGE * (page - 1) : undefined,
|
skip: page ? ITEMS_PER_PAGE * (page - 1) : undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return persons.map((person) => transformPrismaPerson(person));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof Prisma.PrismaClientKnownRequestError) {
|
if (error instanceof Prisma.PrismaClientKnownRequestError) {
|
||||||
throw new DatabaseError(error.message);
|
throw new DatabaseError(error.message);
|
||||||
|
|||||||
@@ -16,6 +16,12 @@ export const ZPersonTableData = z.object({
|
|||||||
attributes: ZAttributes,
|
attributes: ZAttributes,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const ZPersonWithAttributes = ZPerson.extend({
|
||||||
|
attributes: ZAttributes,
|
||||||
|
});
|
||||||
|
|
||||||
|
export type TPersonWithAttributes = z.infer<typeof ZPersonWithAttributes>;
|
||||||
|
|
||||||
export type TPersonTableData = z.infer<typeof ZPersonTableData>;
|
export type TPersonTableData = z.infer<typeof ZPersonTableData>;
|
||||||
|
|
||||||
export type TPerson = z.infer<typeof ZPerson>;
|
export type TPerson = z.infer<typeof ZPerson>;
|
||||||
|
|||||||
Reference in New Issue
Block a user