mirror of
https://github.com/formbricks/formbricks.git
synced 2026-01-25 10:30:30 -06:00
fix customer view in formbricks app, rename pmf overview
This commit is contained in:
@@ -1,13 +1,11 @@
|
||||
"use client";
|
||||
|
||||
import AnalyticsCard from "@/components/AnalyticsCard";
|
||||
import SubmissionDisplay from "@/components/forms/submissions/SubmissionDisplay";
|
||||
import LoadingSpinner from "@/components/LoadingSpinner";
|
||||
import { useCustomer } from "@/lib/customers";
|
||||
import { MergeWithSchema } from "@/lib/submissions";
|
||||
import { convertDateTimeString, onlyUnique, parseUserAgent } from "@/lib/utils";
|
||||
import { useWorkspace } from "@/lib/workspaces";
|
||||
import { convertDateTimeString, onlyUnique } from "@/lib/utils";
|
||||
import { BackIcon, BugIcon, ComplimentIcon, IdeaIcon } from "@formbricks/ui";
|
||||
import { Dialog, Transition } from "@headlessui/react";
|
||||
import { BackIcon } from "@formbricks/ui";
|
||||
import { InboxIcon } from "@heroicons/react/24/outline";
|
||||
import clsx from "clsx";
|
||||
import Link from "next/link";
|
||||
@@ -17,9 +15,6 @@ import EmptyPageFiller from "../EmptyPageFiller";
|
||||
|
||||
export default function SingleCustomerPage() {
|
||||
const router = useRouter();
|
||||
const { workspace, isLoadingWorkspace, isErrorWorkspace } = useWorkspace(
|
||||
router.query.workspaceId?.toString()
|
||||
);
|
||||
const { customer, isLoadingCustomer, isErrorCustomer } = useCustomer(
|
||||
router.query.workspaceId?.toString(),
|
||||
router.query.customerId?.toString()
|
||||
@@ -31,7 +26,7 @@ export default function SingleCustomerPage() {
|
||||
}
|
||||
}, [customer]);
|
||||
|
||||
if (isLoadingWorkspace || isLoadingCustomer) {
|
||||
if (isLoadingCustomer) {
|
||||
return (
|
||||
<div className="flex h-full w-full items-center justify-center">
|
||||
<LoadingSpinner />
|
||||
@@ -39,7 +34,7 @@ export default function SingleCustomerPage() {
|
||||
);
|
||||
}
|
||||
|
||||
if (isErrorWorkspace || isErrorCustomer) {
|
||||
if (isErrorCustomer) {
|
||||
return <div>Error loading ressources. Maybe you don‘t have enough access rights</div>;
|
||||
}
|
||||
return (
|
||||
@@ -110,37 +105,10 @@ export default function SingleCustomerPage() {
|
||||
/>
|
||||
) : null}
|
||||
<div className="relative flex space-x-3">
|
||||
<div>
|
||||
<span
|
||||
className={clsx(
|
||||
"bg-white",
|
||||
"flex h-8 w-8 items-center justify-center rounded-full ring-8 ring-gray-50"
|
||||
)}>
|
||||
{submission.data.feedbackType === "compliment" ? (
|
||||
<ComplimentIcon className="h-6 w-6 text-white" aria-hidden="true" />
|
||||
) : submission.data.feedbackType === "bug" ? (
|
||||
<BugIcon className="h-6 w-6 text-white" aria-hidden="true" />
|
||||
) : (
|
||||
<IdeaIcon className="h-6 w-6 text-white" aria-hidden="true" />
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
<div className="w-full overflow-hidden rounded-lg bg-white shadow">
|
||||
<div className="px-4 py-5 sm:p-6">
|
||||
<div className="flex w-full justify-between">
|
||||
{submission.data.feedbackType === "compliment" ? (
|
||||
<span className="inline-flex items-center rounded-full bg-green-100 px-2.5 py-0.5 text-xs font-medium text-green-800">
|
||||
Love
|
||||
</span>
|
||||
) : submission.data.feedbackType === "bug" ? (
|
||||
<span className="inline-flex items-center rounded-full bg-red-100 px-2.5 py-0.5 text-xs font-medium text-red-800">
|
||||
Bug
|
||||
</span>
|
||||
) : (
|
||||
<span className="inline-flex items-center rounded-full bg-yellow-100 px-2.5 py-0.5 text-xs font-medium text-yellow-800">
|
||||
Idea
|
||||
</span>
|
||||
)}
|
||||
<div></div>
|
||||
|
||||
<div className="text-sm text-gray-400">
|
||||
<time dateTime={convertDateTimeString(submission.createdAt)}>
|
||||
@@ -150,7 +118,20 @@ export default function SingleCustomerPage() {
|
||||
</div>
|
||||
<div className="mt-3">
|
||||
<p className="whitespace-pre-wrap text-sm text-gray-500">
|
||||
{submission.data.message}{" "}
|
||||
{Object.entries(
|
||||
MergeWithSchema(submission.data, submission.form.schema)
|
||||
).map(([key, value]) => (
|
||||
<li key={key} className="py-5">
|
||||
<p className="text-sm font-semibold text-gray-800">{key}</p>
|
||||
<p
|
||||
className={clsx(
|
||||
value ? "text-gray-600" : "text-gray-400",
|
||||
"whitespace-pre-line pt-1 text-sm text-gray-600"
|
||||
)}>
|
||||
{value.toString()}
|
||||
</p>
|
||||
</li>
|
||||
))}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -158,11 +139,9 @@ export default function SingleCustomerPage() {
|
||||
<div className="flex w-full justify-between gap-4">
|
||||
<div>
|
||||
<p className="text-sm font-thin text-gray-500">Device</p>
|
||||
<p className="text-sm text-gray-500">{submission.meta.userAgent}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm font-thin text-gray-500">Page</p>
|
||||
<p className="text-sm text-gray-500">{submission.data.pageUrl}</p>
|
||||
<p className="text-sm text-gray-500">
|
||||
{parseUserAgent(submission.meta.userAgent)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -19,7 +19,7 @@ import SetupInstructions from "./SetupInstructions";
|
||||
|
||||
const tabs = [
|
||||
{ name: "Results", icon: RectangleStackIcon },
|
||||
{ name: "Segments", icon: ChartPieIcon },
|
||||
{ name: "Overview", icon: ChartPieIcon },
|
||||
{ name: "Data Pipelines", icon: ShareIcon },
|
||||
{ name: "Setup Instructions", icon: InformationCircleIcon },
|
||||
];
|
||||
@@ -53,7 +53,7 @@ export default function PMFPage() {
|
||||
</div>
|
||||
{currentTab === "Results" ? (
|
||||
<PMFResults />
|
||||
) : currentTab === "Segments" ? (
|
||||
) : currentTab === "Overview" ? (
|
||||
<SegmentResults />
|
||||
) : currentTab === "Data Pipelines" ? (
|
||||
<PipelinesOverview />
|
||||
|
||||
@@ -28,14 +28,19 @@ export default function FilterNavigation({ submissions, setFilteredSubmissions }
|
||||
if (form) {
|
||||
let newFilteredSubmissions = JSON.parse(JSON.stringify(submissions));
|
||||
for (const filter of filters) {
|
||||
// special routine for archive
|
||||
if (filter.type === "archive") {
|
||||
const archivedSelected = filter.options.find((option) => option.value === "archived")?.active;
|
||||
if (archivedSelected) {
|
||||
newFilteredSubmissions = newFilteredSubmissions.filter((submission) => submission.archived);
|
||||
} else {
|
||||
newFilteredSubmissions = newFilteredSubmissions.filter((submission) => !submission.archived);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
const isAllActive = filter.options.find((option) => option.value === "all")?.active;
|
||||
// no filter is all is selected, if not keep on filtering
|
||||
if (!isAllActive) {
|
||||
// special routine for archive
|
||||
if (filter.type === "archive") {
|
||||
newFilteredSubmissions = newFilteredSubmissions.filter((submission) => submission.archived);
|
||||
continue;
|
||||
}
|
||||
// filter for all other types
|
||||
for (const option of filter.options) {
|
||||
if (option.active) {
|
||||
@@ -86,11 +91,11 @@ export default function FilterNavigation({ submissions, setFilteredSubmissions }
|
||||
}
|
||||
// add archived filter at the end
|
||||
filters.push({
|
||||
name: "archived",
|
||||
label: "Archived",
|
||||
name: "archive",
|
||||
label: "Archive",
|
||||
type: "archive",
|
||||
options: [
|
||||
{ value: "all", label: "All", active: true },
|
||||
{ value: "inbox", label: "Inbox", active: true },
|
||||
{ value: "archived", label: "Archived", active: false },
|
||||
],
|
||||
});
|
||||
|
||||
@@ -39,7 +39,7 @@ export default async function handle(req: NextApiRequest, res: NextApiResponse)
|
||||
},
|
||||
},
|
||||
include: {
|
||||
submissions: true,
|
||||
submissions: { include: { form: true } },
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -5,7 +5,11 @@
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"exports": {
|
||||
".": "./dist",
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/index.mjs",
|
||||
"require": "./dist/index.js"
|
||||
},
|
||||
"./styles.css": "./dist/styles.css"
|
||||
},
|
||||
"module": "dist/index.mjs",
|
||||
|
||||
Reference in New Issue
Block a user