diff --git a/apps/web/src/app/(appListNavigation)/app/chart/[id]/page.tsx b/apps/web/src/app/(appListNavigation)/app/chart/[id]/page.tsx
index 64e65532..e8a3746e 100644
--- a/apps/web/src/app/(appListNavigation)/app/chart/[id]/page.tsx
+++ b/apps/web/src/app/(appListNavigation)/app/chart/[id]/page.tsx
@@ -1,5 +1,7 @@
import { ShowChart } from "@pageComponents/showChart";
-const Page = () => ;
+const Page = ({ params: { id } }: { params: { id: string } }) => (
+
+);
export default Page;
diff --git a/apps/web/src/pageComponents/showChart/components/ShowChartServer.tsx b/apps/web/src/pageComponents/showChart/components/ShowChartServer.tsx
index 854bb3f9..6bc76b7b 100644
--- a/apps/web/src/pageComponents/showChart/components/ShowChartServer.tsx
+++ b/apps/web/src/pageComponents/showChart/components/ShowChartServer.tsx
@@ -1,16 +1,41 @@
+import { SummaryCriteria } from "@oneforall/domain/schema/summary/sumRecordsSchema";
+import { createDataArray } from "@pageComponents/showChart/components/createDataArray";
import ShowChartClient from "@pageComponents/showChart/components/ShowChartClient";
+import { fetchQuery } from "@persistence/database/server/fetchQuery";
+import { parseToRecords } from "@v3/graphql/public/convert/parseToRecords";
+import { GetAppDocument } from "@v3/graphql/public/type";
-export const ShowChartServer = async () => {
- const data = [
- { name: "Group A", value: 400 },
- { name: "Group B", value: 300 },
- { name: "Group C", value: 300 },
- { name: "Group D", value: 200 },
- { name: "Group E", value: 278 },
- { name: "Group F", value: 189 },
- ];
+export const ShowChartServer = async ({ appId }: { appId: string }) => {
+ const { data } = await fetchQuery(GetAppDocument, { appId });
+ const records = parseToRecords(data?.app?.records ?? []);
+
+ const criteria: SummaryCriteria = {
+ groupingFields: {
+ "1718289203212": {
+ id: "1718289203212",
+ fieldName: "値",
+ fieldKind: "text",
+ fieldIndex: 1,
+ options: {},
+ },
+ },
+ summaryFields: {
+ "1718289203213": {
+ id: "1718289203213",
+ fieldName: "数値",
+ fieldKind: "numeric",
+ fieldIndex: 2,
+ options: {
+ thousandsSeparatorPosition: 3,
+ },
+ },
+ },
+ };
+ criteria;
+
+ const dataArray = createDataArray({ records, criteria });
const colors = ["#0088FE", "#00C49F", "#FFBB28", "#FF8042"];
- return ;
+ return ;
};
diff --git a/apps/web/src/pageComponents/showChart/components/createDataArray.test.ts b/apps/web/src/pageComponents/showChart/components/createDataArray.test.ts
new file mode 100644
index 00000000..4e220ca2
--- /dev/null
+++ b/apps/web/src/pageComponents/showChart/components/createDataArray.test.ts
@@ -0,0 +1,104 @@
+import { Records } from "@oneforall/domain/schema/recordSchema";
+import { SummaryCriteria } from "@oneforall/domain/schema/summary/sumRecordsSchema";
+import { createDataArray } from "@pageComponents/showChart/components/createDataArray";
+
+describe("createDataArray", () => {
+ it("", () => {
+ const criteria: SummaryCriteria = {
+ groupingFields: {
+ f1: {
+ id: "f1",
+ fieldName: "値",
+ fieldKind: "text",
+ fieldIndex: 1,
+ options: {},
+ },
+ },
+ summaryFields: {
+ f2: {
+ id: "f2",
+ fieldName: "数値",
+ fieldKind: "numeric",
+ fieldIndex: 2,
+ options: {
+ thousandsSeparatorPosition: 3,
+ },
+ },
+ },
+ };
+
+ const records: Records = {
+ r1: {
+ recordId: "1718289218434",
+ isEditing: false,
+ columns: {
+ f1: {
+ fieldKind: "text",
+ value: "あああ",
+ },
+ f2: {
+ fieldKind: "numeric",
+ value: "100",
+ },
+ },
+ },
+ r2: {
+ recordId: "1718289227545",
+ isEditing: false,
+ columns: {
+ f1: {
+ fieldKind: "text",
+ value: "あああ",
+ },
+ f2: {
+ fieldKind: "numeric",
+ value: "200",
+ },
+ },
+ },
+ r3: {
+ recordId: "1718289236639",
+ isEditing: false,
+ columns: {
+ f1: {
+ fieldKind: "text",
+ value: "いいい",
+ },
+ f2: {
+ fieldKind: "numeric",
+ value: "200",
+ },
+ },
+ },
+ r4: {
+ recordId: "1718895572486",
+ isEditing: false,
+ columns: {
+ f1: {
+ fieldKind: "text",
+ value: "ううう",
+ },
+ f2: {
+ fieldKind: "numeric",
+ value: "500",
+ },
+ },
+ },
+ };
+
+ expect(createDataArray({ records, criteria })).toEqual([
+ {
+ name: "あああ",
+ value: 300,
+ },
+ {
+ name: "いいい",
+ value: 200,
+ },
+ {
+ name: "ううう",
+ value: 500,
+ },
+ ]);
+ });
+});
diff --git a/apps/web/src/pageComponents/showChart/components/createDataArray.ts b/apps/web/src/pageComponents/showChart/components/createDataArray.ts
new file mode 100644
index 00000000..14028b96
--- /dev/null
+++ b/apps/web/src/pageComponents/showChart/components/createDataArray.ts
@@ -0,0 +1,18 @@
+import { sumRecords } from "@oneforall/domain/convert/summary/sumRecords";
+import { Records } from "@oneforall/domain/schema/recordSchema";
+import { SummaryCriteria } from "@oneforall/domain/schema/summary/sumRecordsSchema";
+
+export const createDataArray = ({
+ records,
+ criteria,
+}: {
+ records: Records;
+ criteria: SummaryCriteria;
+}) => {
+ return Object.values(sumRecords(records, criteria)).map((record) => {
+ const name: string = Object.values(record.columns)[0]?.value ?? "";
+ const value: number = record.sum;
+
+ return { name, value };
+ });
+};
diff --git a/apps/web/tsconfig.json b/apps/web/tsconfig.json
index b8dc3d6c..a86c0f5f 100644
--- a/apps/web/tsconfig.json
+++ b/apps/web/tsconfig.json
@@ -1,7 +1,8 @@
{
"extends": "@acme/tsconfig/base.json",
"compilerOptions": {
- "target": "es5",
+ "target": "es2015",
+ "downlevelIteration": true,
"lib": [
"dom",
"dom.iterable",
diff --git a/packages/domain/convert/summary/sumRecords.test.ts b/packages/domain/convert/summary/sumRecords.test.ts
new file mode 100644
index 00000000..16164ce5
--- /dev/null
+++ b/packages/domain/convert/summary/sumRecords.test.ts
@@ -0,0 +1,123 @@
+import { Records } from "../../schema/recordSchema";
+import {
+ SummaryCriteria,
+ SumRecords,
+} from "../../schema/summary/sumRecordsSchema";
+import { sumRecords } from "./sumRecords";
+
+describe("sumRecords", () => {
+ it("", () => {
+ const records: Records = {
+ r1: {
+ recordId: "r1",
+ isEditing: false,
+ columns: {
+ c1: {
+ value: "grouping1",
+ fieldKind: "text",
+ },
+ c2: {
+ value: "100",
+ fieldKind: "numeric",
+ },
+ c3: {
+ value: "r1c3",
+ fieldKind: "text",
+ },
+ },
+ },
+ r2: {
+ recordId: "r2",
+ isEditing: false,
+ columns: {
+ c1: {
+ value: "grouping1",
+ fieldKind: "text",
+ },
+ c2: {
+ value: "200",
+ fieldKind: "numeric",
+ },
+ c3: {
+ value: "r2c3",
+ fieldKind: "text",
+ },
+ },
+ },
+ r3: {
+ recordId: "r3",
+ isEditing: false,
+ columns: {
+ c1: {
+ value: "grouping2",
+ fieldKind: "text",
+ },
+ c2: {
+ value: "300",
+ fieldKind: "numeric",
+ },
+ c3: {
+ value: "r3c3",
+ fieldKind: "text",
+ },
+ },
+ },
+ };
+
+ const criteria: SummaryCriteria = {
+ groupingFields: {
+ c1: {
+ id: "c1",
+ fieldName: "c1",
+ fieldKind: "text",
+ fieldIndex: 1,
+ options: {},
+ },
+ },
+ summaryFields: {
+ c2: {
+ id: "c2",
+ fieldName: "c2",
+ fieldKind: "numeric",
+ fieldIndex: 2,
+ options: {
+ thousandsSeparatorPosition: 3,
+ },
+ },
+ },
+ };
+
+ expect(sumRecords(records, criteria)).toEqual({
+ 0: {
+ columns: {
+ c1: {
+ value: "grouping1",
+ fieldKind: "text",
+ },
+ c2: {
+ value: "300",
+ fieldKind: "numeric",
+ },
+ },
+ sum: 300,
+ average: 150,
+ count: 2,
+ },
+ 1: {
+ columns: {
+ c1: {
+ value: "grouping2",
+ fieldKind: "text",
+ },
+ c2: {
+ value: "300",
+ fieldKind: "numeric",
+ },
+ },
+ sum: 300,
+ average: 300,
+ count: 1,
+ },
+ });
+ });
+});
diff --git a/packages/domain/convert/summary/sumRecords.ts b/packages/domain/convert/summary/sumRecords.ts
new file mode 100644
index 00000000..0a5cee73
--- /dev/null
+++ b/packages/domain/convert/summary/sumRecords.ts
@@ -0,0 +1,68 @@
+import { Records } from "../../schema/recordSchema";
+import {
+ SummaryCriteria,
+ SumRecords,
+} from "../../schema/summary/sumRecordsSchema";
+
+export const sumRecords = (
+ records: Records,
+ criteria: SummaryCriteria,
+): SumRecords => {
+ if (
+ Object.keys(criteria.groupingFields).length < 1 ||
+ Object.keys(criteria.summaryFields).length < 1
+ ) {
+ throw new Error("groupingFields is empty");
+ }
+
+ const groupingFieldId = Object.values(criteria.groupingFields)[0]!.id;
+ const sumFieldId = Object.values(criteria.summaryFields)[0]!.id;
+
+ const uniqueGroupingValues = [
+ ...new Set(
+ Object.values(records).map((r) => r.columns[groupingFieldId]?.value),
+ ),
+ ];
+
+ const result = uniqueGroupingValues
+ .map((groupingValue) => ({
+ groupingFieldId,
+ groupingValue,
+ sumFieldId,
+ }))
+ .flatMap((field) => {
+ const motherRecords = Object.values(records).filter(
+ (record) =>
+ record.columns[field.groupingFieldId]?.value === field.groupingValue,
+ );
+
+ const sum = motherRecords.reduce(
+ (acc, record) => acc + Number(record.columns[field.sumFieldId]?.value),
+ 0,
+ );
+
+ return [
+ {
+ columns: {
+ [field.groupingFieldId]: {
+ value: field.groupingValue ?? "",
+ fieldKind:
+ criteria.groupingFields[field.groupingFieldId]?.fieldKind ??
+ "text",
+ },
+ [field.sumFieldId]: {
+ value: sum.toString(),
+ fieldKind:
+ criteria.summaryFields[field.sumFieldId]?.fieldKind ??
+ "numeric",
+ },
+ },
+ sum,
+ count: motherRecords.length,
+ average: sum / motherRecords.length,
+ },
+ ];
+ });
+
+ return Object.fromEntries(result.map((res, index) => [index, res]));
+};
diff --git a/packages/domain/schema/summary/sumRecordsSchema.ts b/packages/domain/schema/summary/sumRecordsSchema.ts
new file mode 100644
index 00000000..4e68422e
--- /dev/null
+++ b/packages/domain/schema/summary/sumRecordsSchema.ts
@@ -0,0 +1,23 @@
+import { z } from "zod";
+
+import { fieldsSchema } from "../appSchema";
+import { recordColumnsSchema } from "../recordSchema";
+
+const summaryCriteriaSchema = z.object({
+ groupingFields: fieldsSchema,
+ summaryFields: fieldsSchema,
+});
+
+export type SummaryCriteria = z.infer;
+
+const sumRecordsSchema = z.record(
+ z.number(), // index
+ z.object({
+ columns: recordColumnsSchema,
+ sum: z.number(),
+ average: z.number(),
+ count: z.number(),
+ }),
+);
+
+export type SumRecords = z.infer;
diff --git a/packages/domain/tsconfig.json b/packages/domain/tsconfig.json
index ffe3d3df..84f14a8a 100644
--- a/packages/domain/tsconfig.json
+++ b/packages/domain/tsconfig.json
@@ -1,6 +1,8 @@
{
"extends": "@acme/tsconfig/base.json",
"compilerOptions": {
+ "target": "es2015",
+ "downlevelIteration": true,
"tsBuildInfoFile": "node_modules/.cache/tsbuildinfo.json"
},
"exclude": ["node_modules"]
diff --git a/tooling/github/setup/action.yml b/tooling/github/setup/action.yml
index 5685a1d8..6e29909b 100644
--- a/tooling/github/setup/action.yml
+++ b/tooling/github/setup/action.yml
@@ -4,7 +4,7 @@ description: "Common setup steps for Actions"
runs:
using: composite
steps:
- - uses: pnpm/action-setup@v2
+ - uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 20