From e27f541a57ed4e60135a067c6f3ba7c651459505 Mon Sep 17 00:00:00 2001 From: 273* Date: Wed, 13 May 2026 23:50:18 +0900 Subject: [PATCH 01/24] =?UTF-8?q?feat:=20=E3=83=81=E3=83=A3=E3=83=BC?= =?UTF-8?q?=E3=83=88=E3=81=AE=E3=83=87=E3=83=A2=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/explore.tsx | 8 +++- src/components/chart-demo.tsx | 74 +++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 src/components/chart-demo.tsx diff --git a/src/app/explore.tsx b/src/app/explore.tsx index 6cf1c52..dc8b8ad 100644 --- a/src/app/explore.tsx +++ b/src/app/explore.tsx @@ -1,8 +1,9 @@ import { PlatformColor, View } from "react-native"; -import { Host } from "@expo/ui/swift-ui"; +import { Host, VStack } from "@expo/ui/swift-ui"; import { AllformList } from "@/components/all-form-list"; +import ChartDemo from "@/components/chart-demo"; export default function ExploreScreen() { return ( @@ -11,7 +12,10 @@ export default function ExploreScreen() { style={{ flex: 1, backgroundColor: PlatformColor("systemBackground") }} useViewportSizeMeasurement > - + + + + ); diff --git a/src/components/chart-demo.tsx b/src/components/chart-demo.tsx new file mode 100644 index 0000000..28bfe9e --- /dev/null +++ b/src/components/chart-demo.tsx @@ -0,0 +1,74 @@ +import { PlatformColor } from "react-native"; + +import { Chart, ScrollView, Text, VStack } from "@expo/ui/swift-ui"; +import { font, foregroundStyle, frame } from "@expo/ui/swift-ui/modifiers"; + +const weeklyData = [ + { x: "Mon", y: 3 }, + { x: "Tue", y: 7 }, + { x: "Wed", y: 2 }, + { x: "Thu", y: 5 }, + { x: "Fri", y: 8 }, + { x: "Sat", y: 4 }, + { x: "Sun", y: 6 }, +]; + +const trendData = [ + { x: 1, y: 12 }, + { x: 2, y: 18 }, + { x: 3, y: 9 }, + { x: 4, y: 24 }, + { x: 5, y: 20 }, + { x: 6, y: 30 }, + { x: 7, y: 27 }, + { x: 8, y: 35 }, +]; + +export default function ChartDemo() { + return ( + + + {/* 曜日別エントリー数 */} + + + Entries by Day + + + + + {/* エントリー推移 */} + + + Entry Trend + + + + + + ); +} From 2b4f27e544d26884a7ab5fd28ec7e810bb5d63c6 Mon Sep 17 00:00:00 2001 From: 273* Date: Wed, 13 May 2026 23:51:45 +0900 Subject: [PATCH 02/24] =?UTF-8?q?fix:=20=E3=82=BF=E3=83=96=E3=83=90?= =?UTF-8?q?=E3=83=BC=E3=81=AE=E8=A1=A8=E7=A4=BA=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/app-tabs.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/app-tabs.tsx b/src/components/app-tabs.tsx index e7a3559..c2d05d7 100644 --- a/src/components/app-tabs.tsx +++ b/src/components/app-tabs.tsx @@ -21,8 +21,8 @@ export default function AppTabs() { - Report - + Insite + From b9be739f750b85aa29cf9e1e1f4e1aad9443281f Mon Sep 17 00:00:00 2001 From: 273* Date: Thu, 14 May 2026 00:03:36 +0900 Subject: [PATCH 03/24] =?UTF-8?q?fix:=20=E3=82=B8=E3=83=A3=E3=83=BC?= =?UTF-8?q?=E3=83=8A=E3=83=AB=E4=BD=9C=E6=88=90=E7=94=BB=E9=9D=A2=E3=81=AE?= =?UTF-8?q?=E3=83=9C=E3=83=88=E3=83=A0=E3=82=B7=E3=83=BC=E3=83=88=E3=81=AE?= =?UTF-8?q?=E6=8C=99=E5=8B=95=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/journal/field-bottom-sheet.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/components/journal/field-bottom-sheet.tsx b/src/components/journal/field-bottom-sheet.tsx index f316ca1..d84d102 100644 --- a/src/components/journal/field-bottom-sheet.tsx +++ b/src/components/journal/field-bottom-sheet.tsx @@ -12,8 +12,10 @@ import { import { foregroundStyle, frame, + padding, presentationDetents, presentationDragIndicator, + scrollDisabled, } from "@expo/ui/swift-ui/modifiers"; import { FIELD_ICONS, FIELD_LABELS, FieldType } from "@/core/constants"; @@ -48,11 +50,12 @@ export function FieldBottomSheet({ > - + {FIELD_TYPES.map((type) => ( ); From fb079cff53264f6d8782198ee160ffbd9466741b Mon Sep 17 00:00:00 2001 From: 273* Date: Fri, 15 May 2026 00:36:01 +0900 Subject: [PATCH 05/24] =?UTF-8?q?feat:=20=E3=82=A8=E3=83=B3=E3=83=88?= =?UTF-8?q?=E3=83=AA=E3=83=BC=E3=82=92=E5=89=8A=E9=99=A4=E3=81=99=E3=82=8B?= =?UTF-8?q?=E5=87=A6=E7=90=86=E3=82=92=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/(journal)/[id].tsx | 25 ++++++++++---- src/app/(journal)/entry/[id].tsx | 29 +++++++++++----- src/components/entry/entry-list-view.tsx | 44 ++++++++++++++---------- src/db/queries/entries.ts | 22 ++++++++++++ 4 files changed, 87 insertions(+), 33 deletions(-) diff --git a/src/app/(journal)/[id].tsx b/src/app/(journal)/[id].tsx index f9a654d..7d6c08a 100644 --- a/src/app/(journal)/[id].tsx +++ b/src/app/(journal)/[id].tsx @@ -3,6 +3,7 @@ import { useState } from "react"; import { Stack, useLocalSearchParams } from "expo-router"; import { EntryListView } from "@/components/entry/entry-list-view"; +import { deleteAllEntries } from "@/db/queries/entries"; /** * ソート一覧 @@ -29,10 +30,24 @@ const SORT_LABELS: Record = { * ジャーナル詳細(エントリー一覧) */ export default function JournalScreen() { - const { id, name } = useLocalSearchParams<{ id: string; name: string }>(); + const { id: journalId, name } = useLocalSearchParams<{ + id: string; + name: string; + }>(); const [searchText, setSearchText] = useState(""); const [sortKey, setSortKey] = useState("dateDesc"); + const handleDeleteAll = async () => { + // TODO: 削除できないので後ほど修正 + console.log("handleDeleteAll called, journalId:", journalId); + try { + await deleteAllEntries(journalId); + console.log("deleteAllEntries completed"); + } catch (e) { + console.error("deleteAllEntries error:", e); + } + }; + return ( <> { - // Do something - }, + onPress: handleDeleteAll, }, ], }, @@ -147,7 +160,7 @@ export default function JournalScreen() { {/* TODO: 空の場合の処理を追加する */} {/* エントリー一覧にはheaderTitleのデータは含まないので src/app/(journal)/entry/[id].tsx と混同しないように。 */} (); + const router = useRouter(); - const { data: entry } = useLiveQuery(getEntryDetailQuery(id)); + const { id: entryId, journalName } = useLocalSearchParams<{ + id: string; + journalName: string; + }>(); + + const { data: entry } = useLiveQuery(getEntryDetailQuery(entryId)); + + const handleDelete = async () => { + await deleteEntry(entryId); + router.back(); + }; return ( <> [ { type: "menu", @@ -47,9 +60,7 @@ export default function EntryDetailScreen() { name: "trash", }, destructive: true, - onPress: () => { - // Do something - }, + onPress: handleDelete, }, ], }, diff --git a/src/components/entry/entry-list-view.tsx b/src/components/entry/entry-list-view.tsx index df625f1..30eb9e8 100644 --- a/src/components/entry/entry-list-view.tsx +++ b/src/components/entry/entry-list-view.tsx @@ -1,18 +1,14 @@ import { PlatformColor, Pressable, StyleSheet, View } from "react-native"; import { Host, List, Section } from "@expo/ui/swift-ui"; -import { - frame, - headerProminence, - moveDisabled, -} from "@expo/ui/swift-ui/modifiers"; +import { frame, headerProminence } from "@expo/ui/swift-ui/modifiers"; import { useLiveQuery } from "drizzle-orm/expo-sqlite"; import { GlassView } from "expo-glass-effect"; import { useRouter } from "expo-router"; import { SymbolView } from "expo-symbols"; import type { SortKey } from "@/app/(journal)/[id]"; -import { getEntriesQuery } from "@/db/queries/entries"; +import { deleteEntry, getEntriesQuery } from "@/db/queries/entries"; import { buildPreviewEntry, groupByMonth, @@ -68,25 +64,37 @@ export function EntryListView({ useViewportSizeMeasurement > - - {grouped.map(({ month, previewEntries }) => ( -
( +
+ + indices.forEach( + async (i) => await deleteEntry(previewEntries[i].id), + ) + } > - {previewEntries.map((previewEntry) => ( - + {previewEntries.map((entry) => ( + ))} -
- ))} - + +
+ ))}
- router.push(`/(journal)/entry/create?id=${id}&name=${journalName}`) + router.push( + `/(journal)/entry/create?jounalId=${id}&journalName=${journalName}`, + ) } style={styles.fab} > diff --git a/src/db/queries/entries.ts b/src/db/queries/entries.ts index 191d4ba..8b3a90b 100644 --- a/src/db/queries/entries.ts +++ b/src/db/queries/entries.ts @@ -1,3 +1,5 @@ +import { eq } from "drizzle-orm"; + import { db } from "@/db/client"; import { entries, EntryObj, EntryValueObj, entryValues } from "../schemas"; @@ -48,6 +50,26 @@ export const storeEntry = async ( }); }; +/** + * エントリー詳細を削除するクエリ + * @param entryId エントリーID + */ +export const deleteEntry = async (entryId: string) => { + await db.delete(entries).where(eq(entries.id, entryId)); +}; + +/** + * 全てのエントリーを削除するクエリ + * @param journalId ジャーナルID + */ +export const deleteAllEntries = async (journalId?: string) => { + if (journalId) { + await db.delete(entries).where(eq(entries.journalId, journalId)); + } else { + await db.delete(entries); + } +}; + /** エントリー詳細の型 */ export type EntryDetailObj = Awaited< ReturnType From 4777597490c7e4189b780a605ddf021eba6ecb8d Mon Sep 17 00:00:00 2001 From: 273* Date: Fri, 15 May 2026 00:36:53 +0900 Subject: [PATCH 06/24] =?UTF-8?q?refactor:=20=E3=82=B3=E3=83=BC=E3=83=89?= =?UTF-8?q?=E3=81=AE=E5=8F=AF=E8=AA=AD=E6=80=A7=E3=82=92=E9=AB=98=E3=82=81?= =?UTF-8?q?=E3=82=8B=E3=81=9F=E3=82=81=E3=81=AE=E3=83=AA=E3=83=95=E3=82=A1?= =?UTF-8?q?=E3=82=AF=E3=82=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/(journal)/[id].tsx | 22 +-------- src/app/(journal)/entry/create.tsx | 58 +++++++++++------------- src/components/entry/entry-list-view.tsx | 10 ++-- src/components/entry/entry-row.tsx | 8 +++- src/utils/entry/consts.ts | 20 ++++++++ src/utils/entry/preview.ts | 2 +- 6 files changed, 60 insertions(+), 60 deletions(-) create mode 100644 src/utils/entry/consts.ts diff --git a/src/app/(journal)/[id].tsx b/src/app/(journal)/[id].tsx index 7d6c08a..0ec8ea8 100644 --- a/src/app/(journal)/[id].tsx +++ b/src/app/(journal)/[id].tsx @@ -4,27 +4,7 @@ import { Stack, useLocalSearchParams } from "expo-router"; import { EntryListView } from "@/components/entry/entry-list-view"; import { deleteAllEntries } from "@/db/queries/entries"; - -/** - * ソート一覧 - */ -export type SortKey = - | "dateDesc" - | "dateAsc" - | "titleAsc" - | "titleDesc" - | "bookmark"; - -/** - * ソートラベル - */ -const SORT_LABELS: Record = { - dateDesc: "Newest First", - dateAsc: "Oldest First", - titleAsc: "Title (A→Z)", - titleDesc: "Title (Z→A)", - bookmark: "Bookmarked", -}; +import { SORT_LABELS, SortKey } from "@/utils/entry/consts"; /** * ジャーナル詳細(エントリー一覧) diff --git a/src/app/(journal)/entry/create.tsx b/src/app/(journal)/entry/create.tsx index c6e303c..58c63a6 100644 --- a/src/app/(journal)/entry/create.tsx +++ b/src/app/(journal)/entry/create.tsx @@ -1,10 +1,4 @@ -import { - PlatformColor, - Pressable, - Text as RNText, - StyleSheet, - View, -} from "react-native"; +import { PlatformColor, Pressable } from "react-native"; import { useLiveQuery } from "drizzle-orm/expo-sqlite"; import { Stack, useLocalSearchParams, useRouter } from "expo-router"; @@ -20,9 +14,9 @@ import { useEntry } from "@/utils/entry/use-entry"; export default function EntryCreateScreen() { const router = useRouter(); - const { id: jounalId, name } = useLocalSearchParams<{ - id: string; - name: string; + const { jounalId, journalName } = useLocalSearchParams<{ + jounalId: string; + journalName: string; }>(); const { data: fields } = useLiveQuery(getFieldsQuery(jounalId)); @@ -30,19 +24,21 @@ export default function EntryCreateScreen() { const handleEntryCreate = async () => { const { id: newEntryId } = await createEntry(jounalId); - router.replace(`/(journal)/entry/${newEntryId}`); + router.replace(`/(journal)/entry/${newEntryId}?journalName=${journalName}`); }; return ( <> ( - - New Entry - {name} - - ), + title: journalName, + headerLargeTitleEnabled: true, + // headerTitle: () => ( + // + // New Entry + // {journalName} + // + // ), headerRight: () => ( // エントリー作成では disabled は設定しない @@ -63,17 +59,17 @@ export default function EntryCreateScreen() { ); } -const styles = StyleSheet.create({ - headerTitle: { - alignItems: "center", - }, - title: { - fontSize: 17, - fontWeight: "600", - color: PlatformColor("label"), - }, - subtitle: { - fontSize: 14, - color: PlatformColor("secondaryLabel"), - }, -}); +// const styles = StyleSheet.create({ +// headerTitle: { +// alignItems: "center", +// }, +// title: { +// fontSize: 17, +// fontWeight: "600", +// color: PlatformColor("label"), +// }, +// subtitle: { +// fontSize: 14, +// color: PlatformColor("secondaryLabel"), +// }, +// }); diff --git a/src/components/entry/entry-list-view.tsx b/src/components/entry/entry-list-view.tsx index 30eb9e8..9a7dcca 100644 --- a/src/components/entry/entry-list-view.tsx +++ b/src/components/entry/entry-list-view.tsx @@ -7,8 +7,8 @@ import { GlassView } from "expo-glass-effect"; import { useRouter } from "expo-router"; import { SymbolView } from "expo-symbols"; -import type { SortKey } from "@/app/(journal)/[id]"; import { deleteEntry, getEntriesQuery } from "@/db/queries/entries"; +import { type SortKey } from "@/utils/entry/consts"; import { buildPreviewEntry, groupByMonth, @@ -19,7 +19,7 @@ import { EntryRow } from "./entry-row"; type Props = { /** ジャーナル id */ - id: string; + journalId: string; /** ジャーナル */ journalName: string; /** 検索テキスト */ @@ -32,14 +32,14 @@ type Props = { * エントリー一覧画面 */ export function EntryListView({ - id, + journalId, journalName, searchText = "", sortKey = "dateDesc", }: Props) { const router = useRouter(); - const { data: dbEntries } = useLiveQuery(getEntriesQuery(id)); + const { data: dbEntries } = useLiveQuery(getEntriesQuery(journalId)); // エントリープレビュー一覧に変換 const previewEntries = dbEntries.map(buildPreviewEntry); @@ -93,7 +93,7 @@ export function EntryListView({ router.push( - `/(journal)/entry/create?jounalId=${id}&journalName=${journalName}`, + `/(journal)/entry/create?jounalId=${journalId}&journalName=${journalName}`, ) } style={styles.fab} diff --git a/src/components/entry/entry-row.tsx b/src/components/entry/entry-row.tsx index c78be6b..0eaae1c 100644 --- a/src/components/entry/entry-row.tsx +++ b/src/components/entry/entry-row.tsx @@ -10,6 +10,8 @@ import { PreviewEntryObj } from "@/utils/entry/preview"; const secondary = foregroundStyle({ type: "hierarchical", style: "secondary" }); type Props = { + /** ジャーナル */ + journalName: string; /** エントリーデータ */ entry: PreviewEntryObj; }; @@ -17,12 +19,14 @@ type Props = { /** * エントリー行 */ -export function EntryRow({ entry }: Props) { +export function EntryRow({ journalName, entry }: Props) { const router = useRouter(); return ( + + + + + + -