Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/dev' into dev
Browse files Browse the repository at this point in the history
# Conflicts:
#	src/lib/constants.ts
  • Loading branch information
mikecao committed Jun 20, 2024
2 parents 5108b91 + f3efe0c commit 19d5ac0
Show file tree
Hide file tree
Showing 23 changed files with 500 additions and 10 deletions.
1 change: 1 addition & 0 deletions src/app/(main)/console/TestConsole.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export function TestConsole({ websiteId }: { websiteId: string }) {
boolean: true,
booleanError: 'true',
time: new Date(),
user: `user${Math.round(Math.random() * 10)}`,
number: 1,
number2: Math.random() * 100,
time2: new Date().toISOString(),
Expand Down
2 changes: 2 additions & 0 deletions src/app/(main)/reports/[reportId]/ReportPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import InsightsReport from '../insights/InsightsReport';
import JourneyReport from '../journey/JourneyReport';
import RetentionReport from '../retention/RetentionReport';
import UTMReport from '../utm/UTMReport';
import RevenueReport from '../revenue/RevenueReport';

const reports = {
funnel: FunnelReport,
Expand All @@ -16,6 +17,7 @@ const reports = {
utm: UTMReport,
goals: GoalReport,
journey: JourneyReport,
revenue: RevenueReport,
};

export default function ReportPage({ reportId }: { reportId: string }) {
Expand Down
6 changes: 6 additions & 0 deletions src/app/(main)/reports/create/ReportTemplates.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ export function ReportTemplates({ showHeader = true }: { showHeader?: boolean })
url: renderTeamUrl('/reports/journey'),
icon: <Path />,
},
{
title: formatMessage(labels.revenue),
description: formatMessage(labels.revenueDescription),
url: renderTeamUrl('/reports/revenue'),
icon: <Path />,
},
];

return (
Expand Down
98 changes: 98 additions & 0 deletions src/app/(main)/reports/revenue/RevenueChart.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import BarChart, { BarChartProps } from 'components/charts/BarChart';
import { useLocale, useMessages } from 'components/hooks';
import MetricCard from 'components/metrics/MetricCard';
import MetricsBar from 'components/metrics/MetricsBar';
import { renderDateLabels } from 'lib/charts';
import { formatLongNumber } from 'lib/format';
import { useContext, useMemo } from 'react';
import { ReportContext } from '../[reportId]/Report';

export interface PageviewsChartProps extends BarChartProps {
isLoading?: boolean;
}

export function RevenueChart({ isLoading, ...props }: PageviewsChartProps) {
const { formatMessage, labels } = useMessages();
const { locale } = useLocale();
const { report } = useContext(ReportContext);
const { data, parameters } = report || {};

const chartData = useMemo(() => {
if (!data) {
return {};
}

return {
datasets: [
{
label: formatMessage(labels.average),
data: data?.chart.map(a => ({ x: a.time, y: a.avg })),
borderWidth: 2,
backgroundColor: '#8601B0',
borderColor: '#8601B0',
order: 1,
},
{
label: formatMessage(labels.total),
data: data?.chart.map(a => ({ x: a.time, y: a.sum })),
borderWidth: 2,
backgroundColor: '#f15bb5',
borderColor: '#f15bb5',
order: 2,
},
],
};
}, [data, locale]);

const metricData = useMemo(() => {
if (!data) {
return [];
}

const { sum, avg, count, uniqueCount } = data.total;

return [
{
value: sum,
label: formatMessage(labels.total),
formatValue: formatLongNumber,
},
{
value: avg,
label: formatMessage(labels.average),
formatValue: formatLongNumber,
},
{
value: count,
label: formatMessage(labels.transactions),
formatValue: formatLongNumber,
},
{
value: uniqueCount,
label: formatMessage(labels.uniqueCustomers),
formatValue: formatLongNumber,
},
] as any;
}, [data, locale]);

return (
<>
<MetricsBar isFetched={data}>
{metricData?.map(({ label, value, formatValue }) => {
return <MetricCard key={label} value={value} label={label} formatValue={formatValue} />;
})}
</MetricsBar>
{data && (
<BarChart
{...props}
data={chartData}
unit={parameters?.dateRange.unit}
isLoading={isLoading}
renderXLabel={renderDateLabels(parameters?.dateRange.unit, locale)}
/>
)}
</>
);
}

export default RevenueChart;
51 changes: 51 additions & 0 deletions src/app/(main)/reports/revenue/RevenueParameters.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { useMessages } from 'components/hooks';
import { useContext } from 'react';
import { Form, FormButtons, FormInput, FormRow, SubmitButton, TextField } from 'react-basics';
import BaseParameters from '../[reportId]/BaseParameters';
import { ReportContext } from '../[reportId]/Report';

export function RevenueParameters() {
const { report, runReport, isRunning } = useContext(ReportContext);
const { formatMessage, labels } = useMessages();

const { id, parameters } = report || {};
const { websiteId, dateRange } = parameters || {};
const queryDisabled = !websiteId || !dateRange;

const handleSubmit = (data: any, e: any) => {
e.stopPropagation();
e.preventDefault();

if (!queryDisabled) {
runReport(data);
}
};

return (
<Form values={parameters} onSubmit={handleSubmit} preventSubmit={true}>
<BaseParameters showDateSelect={true} allowWebsiteSelect={!id} />
<FormRow label={formatMessage(labels.event)}>
<FormInput name="eventName" rules={{ required: formatMessage(labels.required) }}>
<TextField autoComplete="off" />
</FormInput>
</FormRow>
<FormRow label={formatMessage(labels.revenueProperty)}>
<FormInput name="revenueProperty" rules={{ required: formatMessage(labels.required) }}>
<TextField autoComplete="off" />
</FormInput>
</FormRow>
<FormRow label={formatMessage(labels.userProperty)}>
<FormInput name="userProperty">
<TextField autoComplete="off" />
</FormInput>
</FormRow>
<FormButtons>
<SubmitButton variant="primary" disabled={queryDisabled} isLoading={isRunning}>
{formatMessage(labels.runQuery)}
</SubmitButton>
</FormButtons>
</Form>
);
}

export default RevenueParameters;
10 changes: 10 additions & 0 deletions src/app/(main)/reports/revenue/RevenueReport.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.filters {
display: flex;
flex-direction: column;
justify-content: space-between;
border: 1px solid var(--base400);
border-radius: var(--border-radius);
line-height: 32px;
padding: 10px;
overflow: hidden;
}
27 changes: 27 additions & 0 deletions src/app/(main)/reports/revenue/RevenueReport.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import RevenueChart from './RevenueChart';
import RevenueParameters from './RevenueParameters';
import Report from '../[reportId]/Report';
import ReportHeader from '../[reportId]/ReportHeader';
import ReportMenu from '../[reportId]/ReportMenu';
import ReportBody from '../[reportId]/ReportBody';
import Target from 'assets/target.svg';
import { REPORT_TYPES } from 'lib/constants';

const defaultParameters = {
type: REPORT_TYPES.revenue,
parameters: { Revenue: [] },
};

export default function RevenueReport({ reportId }: { reportId?: string }) {
return (
<Report reportId={reportId} defaultParameters={defaultParameters}>
<ReportHeader icon={<Target />} />
<ReportMenu>
<RevenueParameters />
</ReportMenu>
<ReportBody>
<RevenueChart />
</ReportBody>
</Report>
);
}
6 changes: 6 additions & 0 deletions src/app/(main)/reports/revenue/RevenueReportPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
'use client';
import RevenueReport from './RevenueReport';

export default function RevenueReportPage() {
return <RevenueReport />;
}
10 changes: 10 additions & 0 deletions src/app/(main)/reports/revenue/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import RevenueReportPage from './RevenueReportPage';
import { Metadata } from 'next';

export default function () {
return <RevenueReportPage />;
}

export const metadata: Metadata = {
title: 'Revenue Report',
};
2 changes: 1 addition & 1 deletion src/components/hooks/queries/useReport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { useMessages } from '../useMessages';

export function useReport(
reportId: string,
defaultParameters: { type: string; parameters: { [key: string]: any } },
defaultParameters?: { type: string; parameters: { [key: string]: any } },
) {
const [report, setReport] = useState(null);
const [isRunning, setIsRunning] = useState(false);
Expand Down
3 changes: 2 additions & 1 deletion src/components/hooks/useFilterParams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export function useFilterParams(websiteId: string) {
const { startDate, endDate, unit } = dateRange;
const { timezone } = useTimezone();
const {
query: { url, referrer, title, query, os, browser, device, country, region, city, event },
query: { url, referrer, title, query, host, os, browser, device, country, region, city, event },
} = useNavigation();

return {
Expand All @@ -20,6 +20,7 @@ export function useFilterParams(websiteId: string) {
referrer,
title,
query,
host,
os,
browser,
device,
Expand Down
9 changes: 9 additions & 0 deletions src/components/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ export const labels = defineMessages({
none: { id: 'label.none', defaultMessage: 'None' },
clearAll: { id: 'label.clear-all', defaultMessage: 'Clear all' },
property: { id: 'label.property', defaultMessage: 'Property' },
revenueProperty: { id: 'label.revenue-property', defaultMessage: 'Revenue Property' },
userProperty: { id: 'label.user-property', defaultMessage: 'User Property' },
today: { id: 'label.today', defaultMessage: 'Today' },
lastHours: { id: 'label.last-hours', defaultMessage: 'Last {x} hours' },
yesterday: { id: 'label.yesterday', defaultMessage: 'Yesterday' },
Expand Down Expand Up @@ -155,6 +157,11 @@ export const labels = defineMessages({
id: 'label.funnel-description',
defaultMessage: 'Understand the conversion and drop-off rate of users.',
},
revenue: { id: 'label.revenue', defaultMessage: 'Revenue' },
revenueDescription: {
id: 'label.revenue-description',
defaultMessage: 'Look into your revenue across time.',
},
url: { id: 'label.url', defaultMessage: 'URL' },
urls: { id: 'label.urls', defaultMessage: 'URLs' },
add: { id: 'label.add', defaultMessage: 'Add' },
Expand Down Expand Up @@ -222,6 +229,8 @@ export const labels = defineMessages({
select: { id: 'label.select', defaultMessage: 'Select' },
myAccount: { id: 'label.my-account', defaultMessage: 'My account' },
transfer: { id: 'label.transfer', defaultMessage: 'Transfer' },
transactions: { id: 'label.transactions', defaultMessage: 'Transactions' },
uniqueCustomers: { id: 'label.uniqueCustomers', defaultMessage: 'Unique Customers' },
viewedPage: {
id: 'message.viewed-page',
defaultMessage: 'Viewed page',
Expand Down
5 changes: 4 additions & 1 deletion src/lib/clickhouse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,10 @@ async function parseFilters(websiteId: string, filters: QueryFilters = {}, optio
};
}

async function rawQuery(query: string, params: Record<string, unknown> = {}): Promise<unknown> {
async function rawQuery<T = unknown>(
query: string,
params: Record<string, unknown> = {},
): Promise<T> {
if (process.env.LOG_QUERY) {
log('QUERY:\n', query);
log('PARAMETERS:\n', params);
Expand Down
1 change: 1 addition & 0 deletions src/lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ export const REPORT_TYPES = {
retention: 'retention',
utm: 'utm',
journey: 'journey',
revenue: 'revenue',
} as const;

export const REPORT_PARAMETERS = {
Expand Down
1 change: 1 addition & 0 deletions src/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ export interface QueryFilters {
referrer?: string;
title?: string;
query?: string;
host?: string;
os?: string;
browser?: string;
device?: string;
Expand Down
2 changes: 1 addition & 1 deletion src/pages/api/reports/[reportId].ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const schema: YupRequest = {
websiteId: yup.string().uuid().required(),
type: yup
.string()
.matches(/funnel|insights|retention|utm|goals|journey/i)
.matches(/funnel|insights|retention|utm|goals|journey|revenue/i)
.required(),
name: yup.string().max(200).required(),
description: yup.string().max(500),
Expand Down
2 changes: 1 addition & 1 deletion src/pages/api/reports/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const schema = {
name: yup.string().max(200).required(),
type: yup
.string()
.matches(/funnel|insights|retention|utm|goals|journey/i)
.matches(/funnel|insights|retention|utm|goals|journey|revenue/i)
.required(),
description: yup.string().max(500),
parameters: yup
Expand Down
Loading

0 comments on commit 19d5ac0

Please sign in to comment.