@aiquants/daily-report 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10,49 +10,49 @@ type DailyReportItem = {
10
10
  };
11
11
  /** 面談者情報。 */
12
12
  type DailyReportInterviewer = {
13
- name: string;
14
- affiliation: string | null;
13
+ name?: string | null;
14
+ affiliation?: string | null;
15
15
  };
16
16
  /** レガシー形式 (JSON 埋め込み) のコメント。 */
17
17
  type DailyReportComment = {
18
- name: string | null;
19
- text: string | null;
20
- color: string | null;
18
+ name?: string | null;
19
+ text?: string | null;
20
+ color?: string | null;
21
21
  };
22
22
  /** ラベル定義。 */
23
23
  type DailyReportLabelDef = {
24
24
  id: number;
25
- name: string;
26
- color: string | null;
25
+ name?: string | null;
26
+ color?: string | null;
27
27
  };
28
28
  /** リレーショナルコメント 1 件。`userId` は難読化済み文字列。 */
29
29
  type DailyReportCommentItem = {
30
30
  id: number;
31
- userId: string;
32
- userName: string;
33
- content: string;
34
- createdAt: string;
31
+ userId?: string | null;
32
+ userName?: string | null;
33
+ content?: string | null;
34
+ createdAt?: string | null;
35
35
  isMine: boolean;
36
36
  };
37
37
  /** 日報詳細 (一覧アイテムの遅延解決結果)。`userId` は難読化済み文字列。 */
38
38
  type DailyReportDetail = {
39
39
  reportHubId: number;
40
- date: string | null;
41
- createdAt: string | null;
42
- author: string;
43
- userId: string;
44
- sourceType: string | null;
45
- employeeName: string | null;
46
- updatedBy: string | null;
47
- updatedAt: string | null;
48
- category: string | null;
49
- creationCategory: string | null;
50
- visitTimeFrom: string | null;
51
- visitTimeTo: string | null;
52
- customerName: string | null;
40
+ date?: string | null;
41
+ createdAt?: string | null;
42
+ author?: string | null;
43
+ userId?: string | null;
44
+ sourceType?: string | null;
45
+ employeeName?: string | null;
46
+ updatedBy?: string | null;
47
+ updatedAt?: string | null;
48
+ category?: string | null;
49
+ creationCategory?: string | null;
50
+ visitTimeFrom?: string | null;
51
+ visitTimeTo?: string | null;
52
+ customerName?: string | null;
53
53
  interviewers: DailyReportInterviewer[];
54
- subject: string | null;
55
- content: string | null;
54
+ subject?: string | null;
55
+ content?: string | null;
56
56
  comments: DailyReportComment[];
57
57
  isRead: boolean;
58
58
  isStarred: boolean;
@@ -10,49 +10,49 @@ type DailyReportItem = {
10
10
  };
11
11
  /** 面談者情報。 */
12
12
  type DailyReportInterviewer = {
13
- name: string;
14
- affiliation: string | null;
13
+ name?: string | null;
14
+ affiliation?: string | null;
15
15
  };
16
16
  /** レガシー形式 (JSON 埋め込み) のコメント。 */
17
17
  type DailyReportComment = {
18
- name: string | null;
19
- text: string | null;
20
- color: string | null;
18
+ name?: string | null;
19
+ text?: string | null;
20
+ color?: string | null;
21
21
  };
22
22
  /** ラベル定義。 */
23
23
  type DailyReportLabelDef = {
24
24
  id: number;
25
- name: string;
26
- color: string | null;
25
+ name?: string | null;
26
+ color?: string | null;
27
27
  };
28
28
  /** リレーショナルコメント 1 件。`userId` は難読化済み文字列。 */
29
29
  type DailyReportCommentItem = {
30
30
  id: number;
31
- userId: string;
32
- userName: string;
33
- content: string;
34
- createdAt: string;
31
+ userId?: string | null;
32
+ userName?: string | null;
33
+ content?: string | null;
34
+ createdAt?: string | null;
35
35
  isMine: boolean;
36
36
  };
37
37
  /** 日報詳細 (一覧アイテムの遅延解決結果)。`userId` は難読化済み文字列。 */
38
38
  type DailyReportDetail = {
39
39
  reportHubId: number;
40
- date: string | null;
41
- createdAt: string | null;
42
- author: string;
43
- userId: string;
44
- sourceType: string | null;
45
- employeeName: string | null;
46
- updatedBy: string | null;
47
- updatedAt: string | null;
48
- category: string | null;
49
- creationCategory: string | null;
50
- visitTimeFrom: string | null;
51
- visitTimeTo: string | null;
52
- customerName: string | null;
40
+ date?: string | null;
41
+ createdAt?: string | null;
42
+ author?: string | null;
43
+ userId?: string | null;
44
+ sourceType?: string | null;
45
+ employeeName?: string | null;
46
+ updatedBy?: string | null;
47
+ updatedAt?: string | null;
48
+ category?: string | null;
49
+ creationCategory?: string | null;
50
+ visitTimeFrom?: string | null;
51
+ visitTimeTo?: string | null;
52
+ customerName?: string | null;
53
53
  interviewers: DailyReportInterviewer[];
54
- subject: string | null;
55
- content: string | null;
54
+ subject?: string | null;
55
+ content?: string | null;
56
56
  comments: DailyReportComment[];
57
57
  isRead: boolean;
58
58
  isStarred: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiquants/daily-report",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "Reusable daily-report feature package: shared types/schemas, React (Router v7) UI with virtual scrolling + optimistic updates + SSE sync, and a drizzle (mssql) server layer with DI ports (auth, user resolution, redis, external sources).",
5
5
  "sideEffects": [
6
6
  "**/*.css"
@@ -72,8 +72,8 @@
72
72
  "typescript": "^5.9.3",
73
73
  "vitest": "^4.1.8",
74
74
  "zod": "^3.25.76",
75
- "@aiquants/virtualscroll": "1.19.1",
76
- "@aiquants/swipe-overlay": "1.2.4"
75
+ "@aiquants/swipe-overlay": "1.2.4",
76
+ "@aiquants/virtualscroll": "1.19.1"
77
77
  },
78
78
  "peerDependencies": {
79
79
  "drizzle-orm": ">=1.0.0-beta.4 <2.0.0",
@@ -70,7 +70,7 @@ const formatInterviewerLabel = (interviewer: DailyReportDetail["interviewers"][n
70
70
  if (interviewer.affiliation?.trim()) {
71
71
  return `${interviewer.name}(${interviewer.affiliation})`
72
72
  }
73
- return interviewer.name
73
+ return interviewer.name ?? ""
74
74
  }
75
75
 
76
76
  type DailyReportDetailListProps = {
@@ -953,7 +953,7 @@ const ListReportItem = ({ item, isActive, onSelect }: { item: DailyReportItem; i
953
953
  )
954
954
  }
955
955
 
956
- const previewLines = extractPreviewLines(report.content).map((line, i) => ({
956
+ const previewLines = extractPreviewLines(report.content ?? null).map((line, i) => ({
957
957
  line,
958
958
  key: `${item.reportHubId}-line-${i}`,
959
959
  }))
@@ -392,7 +392,7 @@ export const DailyReportActionProvider = ({ children, user, initialItems = [], u
392
392
 
393
393
  const updatedReport = {
394
394
  ...cached,
395
- commentItems: [...cached.commentItems, newComment].sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()),
395
+ commentItems: [...cached.commentItems, newComment].sort((a, b) => new Date(a.createdAt || 0).getTime() - new Date(b.createdAt || 0).getTime()),
396
396
  }
397
397
  applyDailyReportServerUpdates(reportHubId, updatedReport)
398
398
  // Update mutation time to prevent stale fetch overwrite
@@ -53,7 +53,7 @@ export const useDailyReportSseConnection = ({ isSseEnabled, onMessage }: UseDail
53
53
  const raw = JSON.parse(event.data)
54
54
  const result = dailyReportSseMessageSchema.safeParse(raw)
55
55
  if (!result.success) {
56
- logger.error("SSE Validation Error", result.error.format())
56
+ logger.error("SSE Validation Error:", result.error.flatten(), "raw message:", raw)
57
57
  return
58
58
  }
59
59
  if (result.data.type === "connected") {
@@ -170,11 +170,11 @@ export const DailyReportCache = {
170
170
  // Restore missing "my comments"
171
171
  if (cachedReport) {
172
172
  const serverIds = new Set(report.commentItems.map((c) => c.id))
173
- const missing = cachedReport.commentItems.filter((c) => !serverIds.has(c.id) && c.isMine && Date.now() - new Date(c.createdAt).getTime() < 10000)
173
+ const missing = cachedReport.commentItems.filter((c) => !serverIds.has(c.id) && c.isMine && Date.now() - new Date(c.createdAt || 0).getTime() < 10000)
174
174
  if (missing.length > 0) {
175
175
  report = {
176
176
  ...report,
177
- commentItems: [...report.commentItems, ...missing].sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()),
177
+ commentItems: [...report.commentItems, ...missing].sort((a, b) => new Date(a.createdAt || 0).getTime() - new Date(b.createdAt || 0).getTime()),
178
178
  }
179
179
  }
180
180
  }
@@ -32,9 +32,9 @@ export const mergeComments = (legacyComments: DailyReportComment[], modernCommen
32
32
  // 2. Modern コメントの変換
33
33
  const modernUIComments: UIComment[] = modernComments.map((c) => ({
34
34
  id: c.id,
35
- authorName: c.userName,
36
- content: c.content,
37
- createdAt: c.createdAt,
35
+ authorName: c.userName ?? "",
36
+ content: c.content ?? "",
37
+ createdAt: c.createdAt ?? "",
38
38
  isMine: currentUserId ? c.userId === currentUserId : c.isMine,
39
39
  isLegacy: false,
40
40
  }))
@@ -8,49 +8,49 @@ import type { DailyReportCommentItem as DeclaredComment, DailyReportDetail as De
8
8
  // --- サブスキーマ(types.ts の型と構造的に一致させる) ---
9
9
 
10
10
  export const dailyReportInterviewerSchema = z.object({
11
- name: z.string(),
12
- affiliation: z.string().nullable(),
11
+ name: z.string().nullish(),
12
+ affiliation: z.string().nullish(),
13
13
  })
14
14
 
15
15
  export const dailyReportCommentSchema = z.object({
16
- name: z.string().nullable(),
17
- text: z.string().nullable(),
18
- color: z.string().nullable(),
16
+ name: z.string().nullish(),
17
+ text: z.string().nullish(),
18
+ color: z.string().nullish(),
19
19
  })
20
20
 
21
21
  export const dailyReportLabelDefSchema = z.object({
22
22
  id: z.number(),
23
- name: z.string(),
24
- color: z.string().nullable(),
23
+ name: z.string().nullish(),
24
+ color: z.string().nullish(),
25
25
  })
26
26
 
27
27
  export const dailyReportCommentItemSchema = z.object({
28
28
  id: z.number(),
29
- userId: z.string(),
30
- userName: z.string(),
31
- content: z.string(),
32
- createdAt: z.string(),
29
+ userId: z.string().nullish(),
30
+ userName: z.string().nullish(),
31
+ content: z.string().nullish(),
32
+ createdAt: z.string().nullish(),
33
33
  isMine: z.boolean(),
34
34
  })
35
35
 
36
36
  export const dailyReportDetailSchema = z.object({
37
37
  reportHubId: z.number(),
38
- date: z.string().nullable(),
39
- createdAt: z.string().nullable(),
40
- author: z.string(),
41
- userId: z.string(),
42
- sourceType: z.string().nullable(),
43
- employeeName: z.string().nullable(),
44
- updatedBy: z.string().nullable(),
45
- updatedAt: z.string().nullable(),
46
- category: z.string().nullable(),
47
- creationCategory: z.string().nullable(),
48
- visitTimeFrom: z.string().nullable(),
49
- visitTimeTo: z.string().nullable(),
50
- customerName: z.string().nullable(),
38
+ date: z.string().nullish(),
39
+ createdAt: z.string().nullish(),
40
+ author: z.string().nullish(),
41
+ userId: z.string().nullish(),
42
+ sourceType: z.string().nullish(),
43
+ employeeName: z.string().nullish(),
44
+ updatedBy: z.string().nullish(),
45
+ updatedAt: z.string().nullish(),
46
+ category: z.string().nullish(),
47
+ creationCategory: z.string().nullish(),
48
+ visitTimeFrom: z.string().nullish(),
49
+ visitTimeTo: z.string().nullish(),
50
+ customerName: z.string().nullish(),
51
51
  interviewers: z.array(dailyReportInterviewerSchema),
52
- subject: z.string().nullable(),
53
- content: z.string().nullable(),
52
+ subject: z.string().nullish(),
53
+ content: z.string().nullish(),
54
54
  comments: z.array(dailyReportCommentSchema),
55
55
  isRead: z.boolean(),
56
56
  isStarred: z.boolean(),
@@ -111,6 +111,7 @@ export const reportPublishMessageSchema = z.object({
111
111
  reportHubId: z.number(),
112
112
  report: dailyReportDetailSchema,
113
113
  clientTempId: z.string(),
114
+ recipientRawUserId: z.number().optional(),
114
115
  })
115
116
 
116
117
  export const reportDeleteMessageSchema = z.object({
@@ -12,53 +12,53 @@ export type DailyReportItem = {
12
12
 
13
13
  /** 面談者情報。 */
14
14
  export type DailyReportInterviewer = {
15
- name: string
16
- affiliation: string | null
15
+ name?: string | null
16
+ affiliation?: string | null
17
17
  }
18
18
 
19
19
  /** レガシー形式 (JSON 埋め込み) のコメント。 */
20
20
  export type DailyReportComment = {
21
- name: string | null
22
- text: string | null
23
- color: string | null
21
+ name?: string | null
22
+ text?: string | null
23
+ color?: string | null
24
24
  }
25
25
 
26
26
  /** ラベル定義。 */
27
27
  export type DailyReportLabelDef = {
28
28
  id: number
29
- name: string
30
- color: string | null
29
+ name?: string | null
30
+ color?: string | null
31
31
  }
32
32
 
33
33
  /** リレーショナルコメント 1 件。`userId` は難読化済み文字列。 */
34
34
  export type DailyReportCommentItem = {
35
35
  id: number
36
- userId: string
37
- userName: string
38
- content: string
39
- createdAt: string
36
+ userId?: string | null
37
+ userName?: string | null
38
+ content?: string | null
39
+ createdAt?: string | null
40
40
  isMine: boolean
41
41
  }
42
42
 
43
43
  /** 日報詳細 (一覧アイテムの遅延解決結果)。`userId` は難読化済み文字列。 */
44
44
  export type DailyReportDetail = {
45
45
  reportHubId: number
46
- date: string | null
47
- createdAt: string | null
48
- author: string
49
- userId: string
50
- sourceType: string | null
51
- employeeName: string | null
52
- updatedBy: string | null
53
- updatedAt: string | null
54
- category: string | null
55
- creationCategory: string | null
56
- visitTimeFrom: string | null
57
- visitTimeTo: string | null
58
- customerName: string | null
46
+ date?: string | null
47
+ createdAt?: string | null
48
+ author?: string | null
49
+ userId?: string | null
50
+ sourceType?: string | null
51
+ employeeName?: string | null
52
+ updatedBy?: string | null
53
+ updatedAt?: string | null
54
+ category?: string | null
55
+ creationCategory?: string | null
56
+ visitTimeFrom?: string | null
57
+ visitTimeTo?: string | null
58
+ customerName?: string | null
59
59
  interviewers: DailyReportInterviewer[]
60
- subject: string | null
61
- content: string | null
60
+ subject?: string | null
61
+ content?: string | null
62
62
  comments: DailyReportComment[]
63
63
  isRead: boolean
64
64
  isStarred: boolean