feat: Implement GraphQL mutations for activities and children
Add complete GraphQL mutation support for activity tracking and child management: **Activity Mutations:** - createActivity: Create new activities (feeding, sleep, diaper, medication) - updateActivity: Update existing activities - deleteActivity: Delete activities **Child Mutations:** - createChild: Add new children to families - updateChild: Update child information - deleteChild: Soft delete children **Implementation Details:** - Created GraphQL input types (CreateActivityInput, UpdateActivityInput, CreateChildInput, UpdateChildInput) - Implemented ActivityResolver with full CRUD mutations - Implemented ChildResolver with full CRUD mutations - Registered resolvers in GraphQL module with TrackingService and ChildrenService - Auto-generated GraphQL schema with all mutations - All mutations protected with GqlAuthGuard for authentication - Support for JSON metadata fields and Gender enum 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,7 @@ import { Inter } from 'next/font/google';
|
||||
import { ThemeRegistry } from '@/components/ThemeRegistry';
|
||||
import { ErrorBoundary } from '@/components/common/ErrorBoundary';
|
||||
import { ReduxProvider } from '@/components/providers/ReduxProvider';
|
||||
import { ApolloProvider } from '@/components/providers/ApolloProvider';
|
||||
import { AxeProvider } from '@/components/providers/AxeProvider';
|
||||
import { SkipNavigation } from '@/components/common/SkipNavigation';
|
||||
import { VoiceFloatingButton } from '@/components/voice/VoiceFloatingButton';
|
||||
@@ -46,16 +47,18 @@ export default function RootLayout({
|
||||
<AxeProvider>
|
||||
<ErrorBoundary>
|
||||
<ReduxProvider>
|
||||
<ThemeRegistry>
|
||||
<FocusManagementProvider>
|
||||
<SkipNavigation />
|
||||
{/* <PerformanceMonitor /> */}
|
||||
<main id="main-content" tabIndex={-1}>
|
||||
{children}
|
||||
</main>
|
||||
<VoiceFloatingButton />
|
||||
</FocusManagementProvider>
|
||||
</ThemeRegistry>
|
||||
<ApolloProvider>
|
||||
<ThemeRegistry>
|
||||
<FocusManagementProvider>
|
||||
<SkipNavigation />
|
||||
{/* <PerformanceMonitor /> */}
|
||||
<main id="main-content" tabIndex={-1}>
|
||||
{children}
|
||||
</main>
|
||||
<VoiceFloatingButton />
|
||||
</FocusManagementProvider>
|
||||
</ThemeRegistry>
|
||||
</ApolloProvider>
|
||||
</ReduxProvider>
|
||||
</ErrorBoundary>
|
||||
</AxeProvider>
|
||||
|
||||
17
maternal-web/components/providers/ApolloProvider.tsx
Normal file
17
maternal-web/components/providers/ApolloProvider.tsx
Normal file
@@ -0,0 +1,17 @@
|
||||
'use client';
|
||||
|
||||
import { ReactNode } from 'react';
|
||||
import { ApolloProvider as BaseApolloProvider } from '@apollo/client/react';
|
||||
import apolloClient from '@/lib/apollo-client';
|
||||
|
||||
interface ApolloProviderProps {
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
export function ApolloProvider({ children }: ApolloProviderProps) {
|
||||
return (
|
||||
<BaseApolloProvider client={apolloClient}>
|
||||
{children}
|
||||
</BaseApolloProvider>
|
||||
);
|
||||
}
|
||||
57
maternal-web/graphql/queries/dashboard.ts
Normal file
57
maternal-web/graphql/queries/dashboard.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const GET_DASHBOARD = gql`
|
||||
query GetDashboard($childId: String) {
|
||||
dashboard(childId: $childId) {
|
||||
children {
|
||||
id
|
||||
name
|
||||
birthDate
|
||||
gender
|
||||
photoUrl
|
||||
}
|
||||
selectedChild {
|
||||
id
|
||||
name
|
||||
birthDate
|
||||
gender
|
||||
photoUrl
|
||||
}
|
||||
recentActivities {
|
||||
id
|
||||
type
|
||||
startedAt
|
||||
endedAt
|
||||
notes
|
||||
metadata
|
||||
childId
|
||||
loggedBy
|
||||
logger {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
todaySummary {
|
||||
date
|
||||
feedingCount
|
||||
totalFeedingAmount
|
||||
sleepCount
|
||||
totalSleepDuration
|
||||
diaperCount
|
||||
medicationCount
|
||||
}
|
||||
familyMembers {
|
||||
userId
|
||||
familyId
|
||||
role
|
||||
user {
|
||||
id
|
||||
name
|
||||
email
|
||||
}
|
||||
}
|
||||
totalChildren
|
||||
totalActivitiesToday
|
||||
}
|
||||
}
|
||||
`;
|
||||
147
maternal-web/package-lock.json
generated
147
maternal-web/package-lock.json
generated
@@ -8,6 +8,7 @@
|
||||
"name": "maternal-web",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"@apollo/client": "^4.0.7",
|
||||
"@emotion/react": "^11.14.0",
|
||||
"@emotion/styled": "^11.14.1",
|
||||
"@hookform/resolvers": "^5.2.2",
|
||||
@@ -21,6 +22,7 @@
|
||||
"date-fns": "^4.1.0",
|
||||
"focus-trap-react": "^11.0.4",
|
||||
"framer-motion": "^12.23.22",
|
||||
"graphql": "^16.11.0",
|
||||
"next": "^15.5.4",
|
||||
"next-pwa": "^5.6.0",
|
||||
"react": "^19.2.0",
|
||||
@@ -80,6 +82,48 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@apollo/client": {
|
||||
"version": "4.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@apollo/client/-/client-4.0.7.tgz",
|
||||
"integrity": "sha512-hZp/mKtAqM+g6buUnu6Wqtyc33QebvfdY0SE46xWea4lU1CxwI57VORy2N2vA9CoCRgYM4ELNXzr6nNErAdhfg==",
|
||||
"license": "MIT",
|
||||
"workspaces": [
|
||||
"dist",
|
||||
"codegen",
|
||||
"scripts/codemods/ac3-to-ac4"
|
||||
],
|
||||
"dependencies": {
|
||||
"@graphql-typed-document-node/core": "^3.1.1",
|
||||
"@wry/caches": "^1.0.0",
|
||||
"@wry/equality": "^0.5.6",
|
||||
"@wry/trie": "^0.5.0",
|
||||
"graphql-tag": "^2.12.6",
|
||||
"optimism": "^0.18.0",
|
||||
"tslib": "^2.3.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"graphql": "^16.0.0",
|
||||
"graphql-ws": "^5.5.5 || ^6.0.3",
|
||||
"react": "^17.0.0 || ^18.0.0 || >=19.0.0-rc",
|
||||
"react-dom": "^17.0.0 || ^18.0.0 || >=19.0.0-rc",
|
||||
"rxjs": "^7.3.0",
|
||||
"subscriptions-transport-ws": "^0.9.0 || ^0.11.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"graphql-ws": {
|
||||
"optional": true
|
||||
},
|
||||
"react": {
|
||||
"optional": true
|
||||
},
|
||||
"react-dom": {
|
||||
"optional": true
|
||||
},
|
||||
"subscriptions-transport-ws": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@asamuzakjp/css-color": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.2.0.tgz",
|
||||
@@ -2298,6 +2342,15 @@
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@graphql-typed-document-node/core": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz",
|
||||
"integrity": "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@hookform/resolvers": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-5.2.2.tgz",
|
||||
@@ -5321,6 +5374,54 @@
|
||||
"@xtuc/long": "4.2.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@wry/caches": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@wry/caches/-/caches-1.0.1.tgz",
|
||||
"integrity": "sha512-bXuaUNLVVkD20wcGBWRyo7j9N3TxePEWFZj2Y+r9OoUzfqmavM84+mFykRicNsBqatba5JLay1t48wxaXaWnlA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tslib": "^2.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@wry/context": {
|
||||
"version": "0.7.4",
|
||||
"resolved": "https://registry.npmjs.org/@wry/context/-/context-0.7.4.tgz",
|
||||
"integrity": "sha512-jmT7Sb4ZQWI5iyu3lobQxICu2nC/vbUhP0vIdd6tHC9PTfenmRmuIFqktc6GH9cgi+ZHnsLWPvfSvc4DrYmKiQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tslib": "^2.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@wry/equality": {
|
||||
"version": "0.5.7",
|
||||
"resolved": "https://registry.npmjs.org/@wry/equality/-/equality-0.5.7.tgz",
|
||||
"integrity": "sha512-BRFORjsTuQv5gxcXsuDXx6oGRhuVsEGwZy6LOzRRfgu+eSfxbhUQ9L9YtSEIuIjY/o7g3iWFjrc5eSY1GXP2Dw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tslib": "^2.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@wry/trie": {
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@wry/trie/-/trie-0.5.0.tgz",
|
||||
"integrity": "sha512-FNoYzHawTMk/6KMQoEG5O4PuioX19UbwdQKF44yw0nLfOypfQdjtfZzo/UIJWAJ23sNIFbD1Ug9lbaDGMwbqQA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tslib": "^2.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@xtuc/ieee754": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
|
||||
@@ -8938,6 +9039,30 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/graphql": {
|
||||
"version": "16.11.0",
|
||||
"resolved": "https://registry.npmjs.org/graphql/-/graphql-16.11.0.tgz",
|
||||
"integrity": "sha512-mS1lbMsxgQj6hge1XZ6p7GPhbrtFwUFYi3wRzXAC/FmYnyXMTvvI3td3rjmQ2u8ewXueaSvRPWaEcgVVOT9Jnw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/graphql-tag": {
|
||||
"version": "2.12.6",
|
||||
"resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.6.tgz",
|
||||
"integrity": "sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"graphql": "^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/handlebars": {
|
||||
"version": "4.7.8",
|
||||
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz",
|
||||
@@ -13246,6 +13371,18 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/optimism": {
|
||||
"version": "0.18.1",
|
||||
"resolved": "https://registry.npmjs.org/optimism/-/optimism-0.18.1.tgz",
|
||||
"integrity": "sha512-mLXNwWPa9dgFyDqkNi54sjDyNJ9/fTI6WGBLgnXku1vdKY/jovHfZT5r+aiVeFFLOz+foPNOm5YJ4mqgld2GBQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@wry/caches": "^1.0.0",
|
||||
"@wry/context": "^0.7.0",
|
||||
"@wry/trie": "^0.5.0",
|
||||
"tslib": "^2.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/optionator": {
|
||||
"version": "0.9.4",
|
||||
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
|
||||
@@ -14533,6 +14670,16 @@
|
||||
"queue-microtask": "^1.2.2"
|
||||
}
|
||||
},
|
||||
"node_modules/rxjs": {
|
||||
"version": "7.8.2",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz",
|
||||
"integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/safe-array-concat": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz",
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
"test:e2e:headed": "playwright test --headed"
|
||||
},
|
||||
"dependencies": {
|
||||
"@apollo/client": "^4.0.7",
|
||||
"@emotion/react": "^11.14.0",
|
||||
"@emotion/styled": "^11.14.1",
|
||||
"@hookform/resolvers": "^5.2.2",
|
||||
@@ -28,6 +29,7 @@
|
||||
"date-fns": "^4.1.0",
|
||||
"focus-trap-react": "^11.0.4",
|
||||
"framer-motion": "^12.23.22",
|
||||
"graphql": "^16.11.0",
|
||||
"next": "^15.5.4",
|
||||
"next-pwa": "^5.6.0",
|
||||
"react": "^19.2.0",
|
||||
|
||||
Reference in New Issue
Block a user