@aiquants/daily-report 0.1.1

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.
Files changed (73) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +150 -0
  3. package/dist/client.d.mts +449 -0
  4. package/dist/client.d.ts +449 -0
  5. package/dist/client.js +7 -0
  6. package/dist/client.js.map +1 -0
  7. package/dist/client.mjs +7 -0
  8. package/dist/client.mjs.map +1 -0
  9. package/dist/index.d.mts +42 -0
  10. package/dist/index.d.ts +42 -0
  11. package/dist/index.js +2 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/index.mjs +2 -0
  14. package/dist/index.mjs.map +1 -0
  15. package/dist/logger-D3krZrNK.d.mts +29 -0
  16. package/dist/logger-D3krZrNK.d.ts +29 -0
  17. package/dist/server.d.mts +1515 -0
  18. package/dist/server.d.ts +1515 -0
  19. package/dist/server.js +10 -0
  20. package/dist/server.js.map +1 -0
  21. package/dist/server.mjs +10 -0
  22. package/dist/server.mjs.map +1 -0
  23. package/dist/sse-schema-CK7cUnEo.d.ts +1986 -0
  24. package/dist/sse-schema-yl5AaSsj.d.mts +1986 -0
  25. package/dist/types-CVhwLhSN.d.mts +76 -0
  26. package/dist/types-CVhwLhSN.d.ts +76 -0
  27. package/package.json +108 -0
  28. package/src/client/components/business-day-thumb-overlay.tsx +19 -0
  29. package/src/client/components/daily-report-comment-item.tsx +81 -0
  30. package/src/client/components/daily-report-comment-section.tsx +166 -0
  31. package/src/client/components/daily-report-detail-list.tsx +676 -0
  32. package/src/client/components/daily-report-edit-form.tsx +81 -0
  33. package/src/client/components/daily-report-list.tsx +1024 -0
  34. package/src/client/components/daily-report-page.tsx +147 -0
  35. package/src/client/components/daily-report-resolved-content.tsx +139 -0
  36. package/src/client/components/unread-indicator.tsx +13 -0
  37. package/src/client/config-context.tsx +129 -0
  38. package/src/client/contexts/daily-report-action-context.tsx +910 -0
  39. package/src/client/hooks/use-daily-report-comments.ts +73 -0
  40. package/src/client/hooks/use-daily-report-sse-connection.ts +86 -0
  41. package/src/client/hooks/use-daily-report.spec.ts +155 -0
  42. package/src/client/hooks/use-daily-report.ts +426 -0
  43. package/src/client/hooks/use-dynamic-viewport-height.ts +127 -0
  44. package/src/client/route-helpers.ts +76 -0
  45. package/src/client/ui/button.tsx +42 -0
  46. package/src/client/ui/cn.ts +14 -0
  47. package/src/client/ui/input.tsx +21 -0
  48. package/src/client/ui/label.tsx +16 -0
  49. package/src/client/ui/switch.tsx +19 -0
  50. package/src/client/ui/tabs.tsx +40 -0
  51. package/src/client/ui/textarea.tsx +19 -0
  52. package/src/client/utils/constants.ts +29 -0
  53. package/src/client.ts +21 -0
  54. package/src/index.ts +10 -0
  55. package/src/server/cache.ts +165 -0
  56. package/src/server/etag.ts +18 -0
  57. package/src/server/external-source.ts +60 -0
  58. package/src/server/handlers.ts +543 -0
  59. package/src/server/ports.ts +68 -0
  60. package/src/server/response.ts +37 -0
  61. package/src/server/schema.ts +266 -0
  62. package/src/server/service.spec.ts +97 -0
  63. package/src/server/service.ts +1308 -0
  64. package/src/server/sse-reader.spec.ts +55 -0
  65. package/src/server/sse-reader.ts +223 -0
  66. package/src/server.ts +83 -0
  67. package/src/shared/business-date.spec.ts +61 -0
  68. package/src/shared/business-date.ts +84 -0
  69. package/src/shared/comment-adapter.ts +78 -0
  70. package/src/shared/logger.ts +47 -0
  71. package/src/shared/sse-schema.ts +147 -0
  72. package/src/shared/text-utils.ts +57 -0
  73. package/src/shared/types.ts +76 -0
@@ -0,0 +1,147 @@
1
+ /**
2
+ * Zod schemas for daily-report SSE messages (client/server shared contract).
3
+ * 日報 SSE メッセージの zod スキーマ (client / server 共有契約)。
4
+ */
5
+ import { z } from "zod"
6
+ import type { DailyReportCommentItem as DeclaredComment, DailyReportDetail as DeclaredDetail } from "./types"
7
+
8
+ // --- サブスキーマ(types.ts の型と構造的に一致させる) ---
9
+
10
+ export const dailyReportInterviewerSchema = z.object({
11
+ name: z.string(),
12
+ affiliation: z.string().nullable(),
13
+ })
14
+
15
+ export const dailyReportCommentSchema = z.object({
16
+ name: z.string().nullable(),
17
+ text: z.string().nullable(),
18
+ color: z.string().nullable(),
19
+ })
20
+
21
+ export const dailyReportLabelDefSchema = z.object({
22
+ id: z.number(),
23
+ name: z.string(),
24
+ color: z.string().nullable(),
25
+ })
26
+
27
+ export const dailyReportCommentItemSchema = z.object({
28
+ id: z.number(),
29
+ userId: z.string(),
30
+ userName: z.string(),
31
+ content: z.string(),
32
+ createdAt: z.string(),
33
+ isMine: z.boolean(),
34
+ })
35
+
36
+ export const dailyReportDetailSchema = z.object({
37
+ reportHubId: z.number(),
38
+ date: z.string().nullable(),
39
+ createdAt: z.string().nullable(),
40
+ author: z.string(),
41
+ userId: z.string(),
42
+ employeeName: z.string().nullable(),
43
+ updatedBy: z.string().nullable(),
44
+ updatedAt: z.string().nullable(),
45
+ category: z.string().nullable(),
46
+ creationCategory: z.string().nullable(),
47
+ visitTimeFrom: z.string().nullable(),
48
+ visitTimeTo: z.string().nullable(),
49
+ customerName: z.string().nullable(),
50
+ interviewers: z.array(dailyReportInterviewerSchema),
51
+ subject: z.string().nullable(),
52
+ content: z.string().nullable(),
53
+ comments: z.array(dailyReportCommentSchema),
54
+ isRead: z.boolean(),
55
+ isStarred: z.boolean(),
56
+ labels: z.array(dailyReportLabelDefSchema),
57
+ commentItems: z.array(dailyReportCommentItemSchema),
58
+ })
59
+
60
+ // --- SSE メッセージスキーマ(8種) ---
61
+
62
+ export const connectedMessageSchema = z.object({
63
+ type: z.literal("connected"),
64
+ })
65
+
66
+ export const statusUpdateMessageSchema = z.object({
67
+ type: z.literal("status-update"),
68
+ reportHubId: z.number(),
69
+ statusType: z.enum(["star", "read"]),
70
+ value: z.boolean(),
71
+ clientTempId: z.string(),
72
+ // recipientRawUserId はサーバーサイドフィルタリング専用。
73
+ // SSE ルートが raw JSON から取得してフィルタ後に除去する。
74
+ // クライアントには到達しないが、サーバー側の publish で .parse() を通すため定義が必要。
75
+ recipientRawUserId: z.number().optional(),
76
+ })
77
+
78
+ export const commentAddMessageSchema = z.object({
79
+ type: z.literal("comment-add"),
80
+ reportHubId: z.number(),
81
+ comment: dailyReportCommentItemSchema,
82
+ clientTempId: z.string(),
83
+ })
84
+
85
+ export const commentDeleteMessageSchema = z.object({
86
+ type: z.literal("comment-delete"),
87
+ reportHubId: z.number(),
88
+ commentId: z.number(),
89
+ clientTempId: z.string(),
90
+ })
91
+
92
+ export const reportCreateMessageSchema = z.object({
93
+ type: z.literal("report-create"),
94
+ reportHubId: z.number(),
95
+ report: dailyReportDetailSchema,
96
+ clientTempId: z.string(),
97
+ recipientRawUserId: z.number().optional(),
98
+ })
99
+
100
+ export const reportUpdateMessageSchema = z.object({
101
+ type: z.literal("report-update"),
102
+ reportHubId: z.number(),
103
+ report: dailyReportDetailSchema,
104
+ clientTempId: z.string(),
105
+ recipientRawUserId: z.number().optional(),
106
+ })
107
+
108
+ export const reportPublishMessageSchema = z.object({
109
+ type: z.literal("report-publish"),
110
+ reportHubId: z.number(),
111
+ report: dailyReportDetailSchema,
112
+ clientTempId: z.string(),
113
+ })
114
+
115
+ export const reportDeleteMessageSchema = z.object({
116
+ type: z.literal("report-delete"),
117
+ reportHubId: z.number(),
118
+ clientTempId: z.string(),
119
+ })
120
+
121
+ // --- Discriminated Union ---
122
+
123
+ export const dailyReportSseMessageSchema = z.discriminatedUnion("type", [
124
+ connectedMessageSchema,
125
+ statusUpdateMessageSchema,
126
+ commentAddMessageSchema,
127
+ commentDeleteMessageSchema,
128
+ reportCreateMessageSchema,
129
+ reportUpdateMessageSchema,
130
+ reportPublishMessageSchema,
131
+ reportDeleteMessageSchema,
132
+ ])
133
+
134
+ // --- 型エクスポート ---
135
+
136
+ export type DailyReportSseMessage = z.infer<typeof dailyReportSseMessageSchema>
137
+
138
+ // --- コンパイル時の型互換チェック ---
139
+ // Zod推論型が既存の型定義に代入可能であることを保証する。
140
+ // ここでエラーが出たらスキーマと types.ts がずれている。
141
+
142
+ type _AssertDetailCompat = z.infer<typeof dailyReportDetailSchema> extends DeclaredDetail ? true : never
143
+ type _AssertCommentCompat = z.infer<typeof dailyReportCommentItemSchema> extends DeclaredComment ? true : never
144
+ const _detailCheck: _AssertDetailCompat = true
145
+ const _commentCheck: _AssertCommentCompat = true
146
+ void _detailCheck
147
+ void _commentCheck
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Shared text helpers for daily report view components.
3
+ * 日報ビューコンポーネント向けの共通テキストヘルパー。
4
+ */
5
+
6
+ /**
7
+ * Normalizes nullable text by trimming whitespace and applying fallback.
8
+ * null 許容の文字列をトリムしつつフォールバック値を適用する関数。
9
+ */
10
+ export const fallbackText = (value: string | null | undefined): string => {
11
+ if (!value) {
12
+ return "-"
13
+ }
14
+ const trimmed = value.trim()
15
+ return trimmed === "" ? "-" : trimmed
16
+ }
17
+
18
+ /**
19
+ * Formats a date string to ISO 8601 format (YYYY-MM-DD or YYYY-MM-DDTHH:mm:ss).
20
+ * 日付文字列を ISO 8601 形式 (YYYY-MM-DD または YYYY-MM-DDTHH:mm:ss) に整形する関数。
21
+ */
22
+ export const formatToIsoDate = (value: unknown): string => {
23
+ if (!value) {
24
+ return "-"
25
+ }
26
+ if (typeof value !== "string") {
27
+ // If value is not a string (e.g. Date object), try to convert it to string or handle it
28
+ if (value instanceof Date) {
29
+ return formatToIsoDate(value.toISOString())
30
+ }
31
+ return String(value)
32
+ }
33
+ const trimmed = value.trim()
34
+ if (trimmed === "") {
35
+ return "-"
36
+ }
37
+
38
+ const date = new Date(trimmed)
39
+ if (Number.isNaN(date.getTime())) {
40
+ return trimmed
41
+ }
42
+
43
+ const year = date.getFullYear()
44
+ const month = String(date.getMonth() + 1).padStart(2, "0")
45
+ const day = String(date.getDate()).padStart(2, "0")
46
+
47
+ const hasTime = trimmed.includes(":") || trimmed.includes("T")
48
+
49
+ if (hasTime) {
50
+ const hours = String(date.getHours()).padStart(2, "0")
51
+ const minutes = String(date.getMinutes()).padStart(2, "0")
52
+ const seconds = String(date.getSeconds()).padStart(2, "0")
53
+ return `${year}-${month}-${day}T${hours}:${minutes}:${seconds}`
54
+ }
55
+
56
+ return `${year}-${month}-${day}`
57
+ }
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Core data types shared by the daily-report client and server layers.
3
+ * 日報機能の client / server 層で共有するコアデータ型定義。
4
+ */
5
+
6
+ /** 日報一覧の 1 アイテム (詳細は遅延読み込み)。 */
7
+ export type DailyReportItem = {
8
+ reportHubId: number
9
+ businessDate: string | null
10
+ }
11
+
12
+ /** 面談者情報。 */
13
+ export type DailyReportInterviewer = {
14
+ name: string
15
+ affiliation: string | null
16
+ }
17
+
18
+ /** レガシー形式 (JSON 埋め込み) のコメント。 */
19
+ export type DailyReportComment = {
20
+ name: string | null
21
+ text: string | null
22
+ color: string | null
23
+ }
24
+
25
+ /** ラベル定義。 */
26
+ export type DailyReportLabelDef = {
27
+ id: number
28
+ name: string
29
+ color: string | null
30
+ }
31
+
32
+ /** リレーショナルコメント 1 件。`userId` は難読化済み文字列。 */
33
+ export type DailyReportCommentItem = {
34
+ id: number
35
+ userId: string
36
+ userName: string
37
+ content: string
38
+ createdAt: string
39
+ isMine: boolean
40
+ }
41
+
42
+ /** 日報詳細 (一覧アイテムの遅延解決結果)。`userId` は難読化済み文字列。 */
43
+ export type DailyReportDetail = {
44
+ reportHubId: number
45
+ date: string | null
46
+ createdAt: string | null
47
+ author: string
48
+ userId: string
49
+ employeeName: string | null
50
+ updatedBy: string | null
51
+ updatedAt: string | null
52
+ category: string | null
53
+ creationCategory: string | null
54
+ visitTimeFrom: string | null
55
+ visitTimeTo: string | null
56
+ customerName: string | null
57
+ interviewers: DailyReportInterviewer[]
58
+ subject: string | null
59
+ content: string | null
60
+ comments: DailyReportComment[]
61
+ isRead: boolean
62
+ isStarred: boolean
63
+ labels: DailyReportLabelDef[]
64
+ commentItems: DailyReportCommentItem[]
65
+ }
66
+
67
+ /**
68
+ * Minimal display-user shape consumed by the client layer.
69
+ * client 層が表示に使う最小ユーザー形状 (Google プロフィール等と構造互換)。
70
+ */
71
+ export type DailyReportUser = {
72
+ id: string
73
+ displayName?: string
74
+ name?: { familyName?: string; givenName?: string }
75
+ emails?: { value: string }[]
76
+ }