diff --git a/.scripts/add-catalogs.js b/.scripts/add-catalogs.js new file mode 100644 index 00000000..33bdef00 --- /dev/null +++ b/.scripts/add-catalogs.js @@ -0,0 +1,96 @@ +const fs = require('fs') +const path = require('path') +const YAML = require('yaml') +const { execSync } = require('child_process') + +const scriptDir = path.resolve(__dirname) +const rootDir = path.resolve(scriptDir, '..') +const workspaceConfigPath = path.join(rootDir, 'pnpm-workspace.yaml') + +const loadWorkspaceCatalogs = () => { + const workspaceContent = fs.readFileSync(workspaceConfigPath, 'utf8') + const workspaceConfig = YAML.parse(workspaceContent) + const rootCatalog = workspaceConfig.catalog || {} + const catalogs = workspaceConfig.catalogs || {} + + return { rootCatalog, catalogs } +} + +const getCatalogNameForDependency = (dependency, catalogs) => { + for (const [catalogName, catalogDeps] of Object.entries(catalogs)) { + if (catalogDeps[dependency]) { + return catalogName + } + } + return null +} + +const replaceVersionsWithCatalogs = (packageJsonPath, rootCatalog, catalogs) => { + const packageJsonContent = fs.readFileSync(packageJsonPath, 'utf8') + const packageJson = JSON.parse(packageJsonContent) + + ;['dependencies', 'devDependencies', 'peerDependencies', 'resolutions'].forEach( + (dependencyType) => { + if (packageJson[dependencyType]) { + Object.keys(packageJson[dependencyType]).forEach((dependency) => { + const version = packageJson[dependencyType][dependency] + + if (!version.startsWith('catalog:')) { + let catalogVersion = null + + if (rootCatalog[dependency]) { + catalogVersion = 'catalog:' + } else { + const catalogName = getCatalogNameForDependency(dependency, catalogs) + if (catalogName) { + catalogVersion = `catalog:${catalogName}` + } + } + + if (catalogVersion) { + packageJson[dependencyType][dependency] = catalogVersion + } + } + }) + } + }, + ) + + fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n') +} + +const updatePackagesDependencies = (selectedPackages) => { + const { rootCatalog, catalogs } = loadWorkspaceCatalogs() + const packagesPath = path.join(rootDir, 'packages') + const packageFolders = fs.readdirSync(packagesPath) + + const foldersToProcess = + selectedPackages.length > 0 + ? packageFolders.filter((folder) => selectedPackages.includes(folder)) + : packageFolders + + foldersToProcess.forEach((folder) => { + const packageJsonPath = path.join(packagesPath, folder, 'package.json') + if (fs.existsSync(packageJsonPath)) { + replaceVersionsWithCatalogs(packageJsonPath, rootCatalog, catalogs) + } + }) +} + +const selectedPackages = process.argv.slice(2) +updatePackagesDependencies(selectedPackages) +console.log( + 'Dependencies have been replaced with catalog references successfully. Be sure to double-check the changes made. 😉', +) + +console.log('Regenerating pnpm-lock.yaml...') +try { + execSync('pnpm install --lockfile-only', { stdio: 'inherit', cwd: rootDir }) + console.log('pnpm-lock.yaml has been successfully regenerated.') +} catch (error) { + console.error('An error occurred while regenerating pnpm-lock.yaml:', error) +} + +console.log( + 'The catalog references are now set. Remember to ensure these changes are appropriate before committing.', +) diff --git a/replace-catalogs.js b/.scripts/replace-catalogs.js similarity index 64% rename from replace-catalogs.js rename to .scripts/replace-catalogs.js index 488ab615..99b1fe8d 100644 --- a/replace-catalogs.js +++ b/.scripts/replace-catalogs.js @@ -3,7 +3,9 @@ const path = require('path') const YAML = require('yaml') const { execSync } = require('child_process') -const workspaceConfigPath = path.resolve(__dirname, 'pnpm-workspace.yaml') +const scriptDir = path.resolve(__dirname) +const rootDir = path.resolve(scriptDir, '..') +const workspaceConfigPath = path.join(rootDir, 'pnpm-workspace.yaml') const loadWorkspaceCatalogs = () => { const workspaceContent = fs.readFileSync(workspaceConfigPath, 'utf8') @@ -18,34 +20,37 @@ const replaceCatalogDependencies = (packageJsonPath, rootCatalog, catalogs) => { const packageJsonContent = fs.readFileSync(packageJsonPath, 'utf8') const packageJson = JSON.parse(packageJsonContent) - ;['dependencies', 'devDependencies', 'peerDependencies', 'resolutions'].forEach((depType) => { - if (packageJson[depType]) { - Object.keys(packageJson[depType]).forEach((dep) => { - const version = packageJson[depType][dep] - if (version.startsWith('catalog:')) { - const catalogName = version.split(':')[1] + ;['dependencies', 'devDependencies', 'peerDependencies', 'resolutions'].forEach( + (dependencyType) => { + if (packageJson[dependencyType]) { + Object.keys(packageJson[dependencyType]).forEach((dependency) => { + const version = packageJson[dependencyType][dependency] + if (version.startsWith('catalog:')) { + const catalogName = version.split(':')[1] - let resolvedVersion = - rootCatalog[dep] || (catalogs[catalogName] && catalogs[catalogName][dep]) + let resolvedVersion = + rootCatalog[dependency] || + (catalogs[catalogName] && catalogs[catalogName][dependency]) - if (resolvedVersion) { - packageJson[depType][dep] = resolvedVersion - } else { - console.warn( - `Could not find a matching version for ${dep} in catalog "${catalogName}" or root catalog.`, - ) + if (resolvedVersion) { + packageJson[dependencyType][dependency] = resolvedVersion + } else { + console.warn( + `Could not find a matching version for ${dependency} in catalog "${catalogName}" or root catalog.`, + ) + } } - } - }) - } - }) + }) + } + }, + ) fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n') } const updatePackagesDependencies = (selectedPackages) => { const { rootCatalog, catalogs } = loadWorkspaceCatalogs() - const packagesPath = path.resolve(__dirname, 'packages') + const packagesPath = path.join(rootDir, 'packages') const packageFolders = fs.readdirSync(packagesPath) const foldersToProcess = @@ -69,7 +74,7 @@ console.log( console.log('Regenerating pnpm-lock.yaml...') try { - execSync('pnpm install --lockfile-only', { stdio: 'inherit' }) + execSync('pnpm install --lockfile-only', { stdio: 'inherit', cwd: rootDir }) console.log('pnpm-lock.yaml has been successfully regenerated.') } catch (error) { console.error('An error occurred while regenerating pnpm-lock.yaml:', error) diff --git a/README.md b/README.md index 68989146..84b020ca 100644 --- a/README.md +++ b/README.md @@ -115,10 +115,10 @@ If you need to install a package version that hasn't been published yet, follow ```bash # will replace catalogs for utils and authentication packages - node replace-catalogs.js utils authentication + pnpm replace-catalogs utils authentication # will replace catalogs for all packages - node replace-catalogs.js + pnpm replace-catalogs ``` 2. **Commit and Push**: @@ -141,13 +141,29 @@ If you need to install a package version that hasn't been published yet, follow "@baseapp-frontend/components": "git+https://github.com/silverlogic/baseapp-frontend.git#&path:packages/components", ``` -5. **Undo Changes and Merge**: +5. **Restore Catalog Entries and Merge**: - Once you’ve finished testing or using the non-published version, undo the commit that removed the catalogs. You can now proceed with merging and publishing the changes. + Once you’ve finished testing or using the non-published version, you can restore the catalog entries in one of two ways: - ```bash - git revert - ``` + - Option 1: Revert the Commit + + Revert the commit that removed the catalogs to restore them to their previous state: + + ```bash + git revert + ``` + This will effectively undo the catalog removal and bring back the original entries. + + - Option 2: Run the `add-catalogs` script + + Run the `add-catalogs` script to reapply catalog entries without reverting the commit: + + ```bash + pnpm add-catalogs + ``` + This will update all package.json files to include catalog entries again. + +After using either option, proceed with committing and merging the changes ## Packages Versioning and Publishing diff --git a/package.json b/package.json index 23e1ffa9..0b188e3d 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,8 @@ "release": "turbo run build && changeset publish", "clean": "turbo clean && git clean -xdf node_modules", "format": "prettier --write \"**/*.{ts,tsx,md}\"", - "replace-catalogs": "node replace-catalogs.js", + "add-catalogs": "node .scripts/add-catalogs.js", + "replace-catalogs": "node .scripts/replace-catalogs.js", "prepare": "husky" }, "devDependencies": { diff --git a/packages/authentication/CHANGELOG.md b/packages/authentication/CHANGELOG.md index 5572c08d..bb2ceb3c 100644 --- a/packages/authentication/CHANGELOG.md +++ b/packages/authentication/CHANGELOG.md @@ -1,5 +1,13 @@ # @baseapp-frontend/authentication +## 4.0.2 + +### Patch Changes + +- asd +- Updated dependencies + - @baseapp-frontend/utils@3.0.4 + ## 4.0.1 ### Patch Changes diff --git a/packages/authentication/modules/user/useJWTUser/index.ts b/packages/authentication/modules/user/useJWTUser/index.ts index e16e03ac..58df1dc4 100644 --- a/packages/authentication/modules/user/useJWTUser/index.ts +++ b/packages/authentication/modules/user/useJWTUser/index.ts @@ -41,9 +41,7 @@ const useJWTUser = & JWTContent>({ }) useEffect(() => { - console.log('useJWTUser error:', query.error) // Check if this gets printed if ((query.error as any)?.response?.status === 401) { - console.log('useJWTUser 401 error triggered') queryClient.resetQueries({ queryKey: USER_API_KEY.getUser() }) } }, [query.error]) diff --git a/packages/authentication/package.json b/packages/authentication/package.json index 1ec4f6fc..4445f870 100644 --- a/packages/authentication/package.json +++ b/packages/authentication/package.json @@ -1,7 +1,7 @@ { "name": "@baseapp-frontend/authentication", "description": "Authentication modules.", - "version": "4.0.1", + "version": "4.0.2", "main": "./index.ts", "types": "dist/index.d.ts", "sideEffects": false, diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 216cac3c..6b7ccb60 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -1,5 +1,19 @@ # @baseapp-frontend/components +## 0.0.20 + +### Patch Changes + +- Add Active Tab functionality to the `messages` module. +- Several tweaks on the messages modules in general. +- Adapt `ChatRoomListItem` so it uses a fragment. +- Add `ViewportHeightContainer` component and make sure `MainCointainer` uses variables from the navigation's constants. +- Updated dependencies + - @baseapp-frontend/authentication@4.0.2 + - @baseapp-frontend/design-system@0.0.21 + - @baseapp-frontend/graphql@1.1.12 + - @baseapp-frontend/utils@3.0.4 + ## 0.0.19 ### Patch Changes diff --git a/packages/components/__generated__/AllProfilesListFragment.graphql.ts b/packages/components/__generated__/AllProfilesListFragment.graphql.ts index da09d889..d0b579a5 100644 --- a/packages/components/__generated__/AllProfilesListFragment.graphql.ts +++ b/packages/components/__generated__/AllProfilesListFragment.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<<24f2c4202c29cd58a90fc8b782d50cdc>> * @lightSyntaxTransform * @nogrep */ @@ -19,20 +19,7 @@ export type AllProfilesListFragment$data = { readonly node: | { readonly id: string - readonly image: - | { - readonly url: string - } - | null - | undefined - readonly name: string | null | undefined - readonly pk: number - readonly urlPath: - | { - readonly path: string - } - | null - | undefined + readonly ' $fragmentSpreads': FragmentRefs<'ProfileItemFragment'> } | null | undefined @@ -179,65 +166,9 @@ const node: ReaderFragment = (function () { storageKey: null, }, { - alias: null, args: null, - kind: 'ScalarField', - name: 'pk', - storageKey: null, - }, - { - alias: null, - args: null, - kind: 'ScalarField', - name: 'name', - storageKey: null, - }, - { - alias: null, - args: [ - { - kind: 'Literal', - name: 'height', - value: 48, - }, - { - kind: 'Literal', - name: 'width', - value: 48, - }, - ], - concreteType: 'File', - kind: 'LinkedField', - name: 'image', - plural: false, - selections: [ - { - alias: null, - args: null, - kind: 'ScalarField', - name: 'url', - storageKey: null, - }, - ], - storageKey: 'image(height:48,width:48)', - }, - { - alias: null, - args: null, - concreteType: 'URLPath', - kind: 'LinkedField', - name: 'urlPath', - plural: false, - selections: [ - { - alias: null, - args: null, - kind: 'ScalarField', - name: 'path', - storageKey: null, - }, - ], - storageKey: null, + kind: 'FragmentSpread', + name: 'ProfileItemFragment', }, { alias: null, @@ -268,6 +199,6 @@ const node: ReaderFragment = (function () { } })() -;(node as any).hash = '1f6125a68c568e0d408512ebf4295bee' +;(node as any).hash = '145d7609bc0dcee3b0940096fa289337' export default node diff --git a/packages/components/__generated__/AllProfilesListPaginationQuery.graphql.ts b/packages/components/__generated__/AllProfilesListPaginationQuery.graphql.ts index 4c60a9cf..8da15e9e 100644 --- a/packages/components/__generated__/AllProfilesListPaginationQuery.graphql.ts +++ b/packages/components/__generated__/AllProfilesListPaginationQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<<55c88f2688f5b804fbf33dbcd243bab6>> * @lightSyntaxTransform * @nogrep */ @@ -171,13 +171,6 @@ const node: ConcreteRequest = (function () { plural: false, selections: [ v4 /*: any*/, - { - alias: null, - args: null, - kind: 'ScalarField', - name: 'pk', - storageKey: null, - }, { alias: null, args: null, @@ -191,12 +184,12 @@ const node: ConcreteRequest = (function () { { kind: 'Literal', name: 'height', - value: 48, + value: 100, }, { kind: 'Literal', name: 'width', - value: 48, + value: 100, }, ], concreteType: 'File', @@ -212,7 +205,7 @@ const node: ConcreteRequest = (function () { storageKey: null, }, ], - storageKey: 'image(height:48,width:48)', + storageKey: 'image(height:100,width:100)', }, { alias: null, @@ -268,16 +261,16 @@ const node: ConcreteRequest = (function () { ], }, params: { - cacheID: '98e38667f32793a5b00afd68f19dd97e', + cacheID: '14ee435dd3957e0c7247d383714e53f4', id: null, metadata: {}, name: 'AllProfilesListPaginationQuery', operationKind: 'query', - text: 'query AllProfilesListPaginationQuery(\n $count: Int = 5\n $cursor: String\n $orderBy: String = "-created"\n $q: String = null\n) {\n ...AllProfilesListFragment_40Ewnb\n}\n\nfragment AllProfilesListFragment_40Ewnb on Query {\n allProfiles(after: $cursor, first: $count, orderBy: $orderBy, q: $q) {\n totalCount\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n node {\n id\n pk\n name\n image(width: 48, height: 48) {\n url\n }\n urlPath {\n path\n id\n }\n __typename\n }\n cursor\n }\n }\n}\n', + text: 'query AllProfilesListPaginationQuery(\n $count: Int = 5\n $cursor: String\n $orderBy: String = "-created"\n $q: String = null\n) {\n ...AllProfilesListFragment_40Ewnb\n}\n\nfragment AllProfilesListFragment_40Ewnb on Query {\n allProfiles(after: $cursor, first: $count, orderBy: $orderBy, q: $q) {\n totalCount\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n node {\n id\n ...ProfileItemFragment\n __typename\n }\n cursor\n }\n }\n}\n\nfragment ProfileItemFragment on Profile {\n id\n name\n image(width: 100, height: 100) {\n url\n }\n urlPath {\n path\n id\n }\n}\n', }, } })() -;(node as any).hash = '1f6125a68c568e0d408512ebf4295bee' +;(node as any).hash = '145d7609bc0dcee3b0940096fa289337' export default node diff --git a/packages/components/__generated__/ChatRoomMessagesListPaginationQuery.graphql.ts b/packages/components/__generated__/ChatRoomMessagesListPaginationQuery.graphql.ts index bd83f25f..c919b210 100644 --- a/packages/components/__generated__/ChatRoomMessagesListPaginationQuery.graphql.ts +++ b/packages/components/__generated__/ChatRoomMessagesListPaginationQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<495026d4e55c1a43eb3da3ad9ca39098>> + * @generated SignedSource<> * @lightSyntaxTransform * @nogrep */ @@ -154,6 +154,13 @@ const node: ConcreteRequest = (function () { selections: [v4 /*: any*/], storageKey: null, }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'unreadMessagesCount', + storageKey: null, + }, { alias: null, args: v5 /*: any*/, @@ -235,6 +242,13 @@ const node: ConcreteRequest = (function () { ], storageKey: null, }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'isRead', + storageKey: null, + }, { alias: null, args: null, @@ -334,16 +348,16 @@ const node: ConcreteRequest = (function () { ], }, params: { - cacheID: '0c9cea945886ac8a8546bf73702adb22', + cacheID: '49f246acb3d0ddfb7b9b7cc486130a76', id: null, metadata: {}, name: 'ChatRoomMessagesListPaginationQuery', operationKind: 'query', - text: 'query ChatRoomMessagesListPaginationQuery(\n $count: Int = 20\n $cursor: String\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...MessagesListFragment_1G22uz\n id\n }\n}\n\nfragment MessageItemFragment on Message {\n id\n content\n created\n extraData\n inReplyTo {\n id\n }\n pk\n profile {\n id\n }\n verb\n}\n\nfragment MessagesListFragment_1G22uz on ChatRoom {\n id\n participants {\n totalCount\n }\n allMessages(first: $count, after: $cursor) {\n totalCount\n edges {\n node {\n id\n created\n profile {\n id\n name\n image(height: 32, width: 32) {\n url\n }\n }\n ...MessageItemFragment\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n}\n', + text: 'query ChatRoomMessagesListPaginationQuery(\n $count: Int = 20\n $cursor: String\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...MessagesListFragment_1G22uz\n id\n }\n}\n\nfragment MessageItemFragment on Message {\n id\n content\n created\n extraData\n inReplyTo {\n id\n }\n isRead\n pk\n profile {\n id\n }\n verb\n}\n\nfragment MessagesListFragment_1G22uz on ChatRoom {\n id\n participants {\n totalCount\n }\n unreadMessagesCount\n allMessages(first: $count, after: $cursor) {\n totalCount\n edges {\n node {\n id\n created\n profile {\n id\n name\n image(height: 32, width: 32) {\n url\n }\n }\n isRead\n ...MessageItemFragment\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n}\n', }, } })() -;(node as any).hash = '140657eaa254ee3833f86c73b44cc05a' +;(node as any).hash = '1eebe2365c138d57d71fb4d1365102b9' export default node diff --git a/packages/components/__generated__/ChatRoomQuery.graphql.ts b/packages/components/__generated__/ChatRoomQuery.graphql.ts index e8bde03b..6ada24c9 100644 --- a/packages/components/__generated__/ChatRoomQuery.graphql.ts +++ b/packages/components/__generated__/ChatRoomQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<<33575c6da1146a8319653fa269485d21>> * @lightSyntaxTransform * @nogrep */ @@ -337,6 +337,13 @@ const node: ConcreteRequest = (function () { ], storageKey: null, }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'isRead', + storageKey: null, + }, { alias: null, args: null, @@ -432,16 +439,16 @@ const node: ConcreteRequest = (function () { ], }, params: { - cacheID: '2898527115ec10a9725f8a0b31d7a02c', + cacheID: 'c8ded0d3c408e6149fc07900272389de', id: null, metadata: {}, name: 'ChatRoomQuery', operationKind: 'query', - text: 'query ChatRoomQuery(\n $roomId: ID!\n) {\n chatRoom(id: $roomId) {\n id\n unreadMessagesCount\n participants {\n edges {\n node {\n profile {\n id\n __typename\n name\n image(width: 100, height: 100) {\n url\n }\n }\n id\n }\n }\n }\n ...MessagesListFragment\n }\n}\n\nfragment MessageItemFragment on Message {\n id\n content\n created\n extraData\n inReplyTo {\n id\n }\n pk\n profile {\n id\n }\n verb\n}\n\nfragment MessagesListFragment on ChatRoom {\n id\n participants {\n totalCount\n }\n allMessages(first: 20) {\n totalCount\n edges {\n node {\n id\n created\n profile {\n id\n name\n image(height: 32, width: 32) {\n url\n }\n }\n ...MessageItemFragment\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n}\n', + text: 'query ChatRoomQuery(\n $roomId: ID!\n) {\n chatRoom(id: $roomId) {\n id\n unreadMessagesCount\n participants {\n edges {\n node {\n profile {\n id\n __typename\n name\n image(width: 100, height: 100) {\n url\n }\n }\n id\n }\n }\n }\n ...MessagesListFragment\n }\n}\n\nfragment MessageItemFragment on Message {\n id\n content\n created\n extraData\n inReplyTo {\n id\n }\n isRead\n pk\n profile {\n id\n }\n verb\n}\n\nfragment MessagesListFragment on ChatRoom {\n id\n participants {\n totalCount\n }\n unreadMessagesCount\n allMessages(first: 20) {\n totalCount\n edges {\n node {\n id\n created\n profile {\n id\n name\n image(height: 32, width: 32) {\n url\n }\n }\n isRead\n ...MessageItemFragment\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n}\n', }, } })() -;(node as any).hash = '8ac24822b8b22e3b11eea731ab254d9e' +;(node as any).hash = 'eb4461cf8963b7c4fa0611792ca328aa' export default node diff --git a/packages/components/__generated__/ChatRoomsQuery.graphql.ts b/packages/components/__generated__/ChatRoomsQuery.graphql.ts index f5a784ad..e06663a2 100644 --- a/packages/components/__generated__/ChatRoomsQuery.graphql.ts +++ b/packages/components/__generated__/ChatRoomsQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<<12bb950ec6da82dadc271dbb61bc3534>> * @lightSyntaxTransform * @nogrep */ @@ -87,20 +87,13 @@ const node: ConcreteRequest = (function () { storageKey: null, }, v5 = { - alias: null, - args: null, - kind: 'ScalarField', - name: 'pk', - storageKey: null, - }, - v6 = { alias: null, args: null, kind: 'ScalarField', name: 'name', storageKey: null, }, - v7 = [ + v6 = [ { alias: null, args: null, @@ -109,6 +102,27 @@ const node: ConcreteRequest = (function () { storageKey: null, }, ], + v7 = { + alias: null, + args: [ + { + kind: 'Literal', + name: 'height', + value: 100, + }, + { + kind: 'Literal', + name: 'width', + value: 100, + }, + ], + concreteType: 'File', + kind: 'LinkedField', + name: 'image', + plural: false, + selections: v6 /*: any*/, + storageKey: 'image(height:100,width:100)', + }, v8 = { alias: null, args: null, @@ -123,43 +137,29 @@ const node: ConcreteRequest = (function () { name: 'cursor', storageKey: null, }, - v10 = [v1 /*: any*/], - v11 = { + v10 = { alias: null, args: null, kind: 'ScalarField', name: 'unreadMessagesCount', storageKey: null, }, + v11 = [ + v1 /*: any*/, + { + kind: 'Literal', + name: 'unreadMessages', + value: false, + }, + ], v12 = { - alias: null, - args: [ - { - kind: 'Literal', - name: 'height', - value: 100, - }, - { - kind: 'Literal', - name: 'width', - value: 100, - }, - ], - concreteType: 'File', - kind: 'LinkedField', - name: 'image', - plural: false, - selections: v7 /*: any*/, - storageKey: 'image(height:100,width:100)', - }, - v13 = { alias: null, args: null, kind: 'ScalarField', name: 'content', storageKey: null, }, - v14 = [ + v13 = [ { kind: 'Literal', name: 'first', @@ -245,28 +245,7 @@ const node: ConcreteRequest = (function () { selections: [ v0 /*: any*/, v5 /*: any*/, - v6 /*: any*/, - { - alias: null, - args: [ - { - kind: 'Literal', - name: 'height', - value: 48, - }, - { - kind: 'Literal', - name: 'width', - value: 48, - }, - ], - concreteType: 'File', - kind: 'LinkedField', - name: 'image', - plural: false, - selections: v7 /*: any*/, - storageKey: 'image(height:48,width:48)', - }, + v7 /*: any*/, { alias: null, args: null, @@ -327,9 +306,10 @@ const node: ConcreteRequest = (function () { { kind: 'InlineFragment', selections: [ + v10 /*: any*/, { alias: null, - args: v10 /*: any*/, + args: v11 /*: any*/, concreteType: 'ChatRoomConnection', kind: 'LinkedField', name: 'chatRooms', @@ -352,8 +332,8 @@ const node: ConcreteRequest = (function () { plural: false, selections: [ v0 /*: any*/, - v11 /*: any*/, - v12 /*: any*/, + v10 /*: any*/, + v7 /*: any*/, { alias: null, args: null, @@ -368,7 +348,7 @@ const node: ConcreteRequest = (function () { kind: 'LinkedField', name: 'lastMessage', plural: false, - selections: [v0 /*: any*/, v13 /*: any*/], + selections: [v0 /*: any*/, v12 /*: any*/], storageKey: null, }, { @@ -414,8 +394,8 @@ const node: ConcreteRequest = (function () { selections: [ v0 /*: any*/, v8 /*: any*/, - v6 /*: any*/, - v12 /*: any*/, + v5 /*: any*/, + v7 /*: any*/, ], storageKey: null, }, @@ -430,7 +410,7 @@ const node: ConcreteRequest = (function () { }, { alias: null, - args: v14 /*: any*/, + args: v13 /*: any*/, concreteType: 'MessageConnection', kind: 'LinkedField', name: 'allMessages', @@ -470,7 +450,7 @@ const node: ConcreteRequest = (function () { plural: false, selections: [ v0 /*: any*/, - v6 /*: any*/, + v5 /*: any*/, { alias: null, args: [ @@ -489,13 +469,20 @@ const node: ConcreteRequest = (function () { kind: 'LinkedField', name: 'image', plural: false, - selections: v7 /*: any*/, + selections: v6 /*: any*/, storageKey: 'image(height:32,width:32)', }, ], storageKey: null, }, - v13 /*: any*/, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'isRead', + storageKey: null, + }, + v12 /*: any*/, { alias: null, args: null, @@ -513,7 +500,13 @@ const node: ConcreteRequest = (function () { selections: [v0 /*: any*/], storageKey: null, }, - v5 /*: any*/, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'pk', + storageKey: null, + }, { alias: null, args: null, @@ -535,7 +528,7 @@ const node: ConcreteRequest = (function () { }, { alias: null, - args: v14 /*: any*/, + args: v13 /*: any*/, filters: null, handle: 'connection', key: 'chatRoom_allMessages', @@ -552,18 +545,17 @@ const node: ConcreteRequest = (function () { }, v4 /*: any*/, ], - storageKey: 'chatRooms(first:5)', + storageKey: 'chatRooms(first:5,unreadMessages:false)', }, { alias: null, - args: v10 /*: any*/, - filters: ['q'], + args: v11 /*: any*/, + filters: ['q', 'unreadMessages'], handle: 'connection', key: 'roomsList_chatRooms', kind: 'LinkedHandle', name: 'chatRooms', }, - v11 /*: any*/, ], type: 'ChatRoomsInterface', abstractKey: '__isChatRoomsInterface', @@ -577,12 +569,12 @@ const node: ConcreteRequest = (function () { ], }, params: { - cacheID: '8e8cc1f1c6a69c0e11cff5d53c2b0db4', + cacheID: '4a48d3b542ae8a6f07fae291e58e9f8d', id: null, metadata: {}, name: 'ChatRoomsQuery', operationKind: 'query', - text: 'query ChatRoomsQuery {\n ...AllProfilesListFragment\n me {\n id\n profile {\n id\n ...RoomsListFragment\n }\n }\n}\n\nfragment AllProfilesListFragment on Query {\n allProfiles(first: 5, orderBy: "-created") {\n totalCount\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n node {\n id\n pk\n name\n image(width: 48, height: 48) {\n url\n }\n urlPath {\n path\n id\n }\n __typename\n }\n cursor\n }\n }\n}\n\nfragment MessageItemFragment on Message {\n id\n content\n created\n extraData\n inReplyTo {\n id\n }\n pk\n profile {\n id\n }\n verb\n}\n\nfragment MessagesListFragment on ChatRoom {\n id\n participants {\n totalCount\n }\n allMessages(first: 20) {\n totalCount\n edges {\n node {\n id\n created\n profile {\n id\n name\n image(height: 32, width: 32) {\n url\n }\n }\n ...MessageItemFragment\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n}\n\nfragment RoomFragment on ChatRoom {\n id\n unreadMessagesCount\n image(width: 100, height: 100) {\n url\n }\n lastMessageTime\n lastMessage {\n id\n content\n }\n title\n participants {\n totalCount\n edges {\n node {\n id\n profile {\n id\n __typename\n name\n image(width: 100, height: 100) {\n url\n }\n }\n }\n }\n }\n ...MessagesListFragment\n}\n\nfragment RoomsListFragment on ChatRoomsInterface {\n __isChatRoomsInterface: __typename\n id\n chatRooms(first: 5) {\n edges {\n node {\n id\n unreadMessagesCount\n ...RoomFragment\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n unreadMessagesCount\n}\n', + text: 'query ChatRoomsQuery {\n ...AllProfilesListFragment\n me {\n id\n profile {\n id\n ...RoomsListFragment\n }\n }\n}\n\nfragment AllProfilesListFragment on Query {\n allProfiles(first: 5, orderBy: "-created") {\n totalCount\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n node {\n id\n ...ProfileItemFragment\n __typename\n }\n cursor\n }\n }\n}\n\nfragment MessageItemFragment on Message {\n id\n content\n created\n extraData\n inReplyTo {\n id\n }\n isRead\n pk\n profile {\n id\n }\n verb\n}\n\nfragment MessagesListFragment on ChatRoom {\n id\n participants {\n totalCount\n }\n unreadMessagesCount\n allMessages(first: 20) {\n totalCount\n edges {\n node {\n id\n created\n profile {\n id\n name\n image(height: 32, width: 32) {\n url\n }\n }\n isRead\n ...MessageItemFragment\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n}\n\nfragment ProfileItemFragment on Profile {\n id\n name\n image(width: 100, height: 100) {\n url\n }\n urlPath {\n path\n id\n }\n}\n\nfragment RoomFragment on ChatRoom {\n id\n unreadMessagesCount\n image(width: 100, height: 100) {\n url\n }\n lastMessageTime\n lastMessage {\n id\n content\n }\n title\n participants {\n totalCount\n edges {\n node {\n id\n profile {\n id\n __typename\n name\n image(width: 100, height: 100) {\n url\n }\n }\n }\n }\n }\n ...MessagesListFragment\n}\n\nfragment RoomsListFragment on ChatRoomsInterface {\n __isChatRoomsInterface: __typename\n id\n unreadMessagesCount\n chatRooms(first: 5, unreadMessages: false) {\n edges {\n node {\n id\n unreadMessagesCount\n ...RoomFragment\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n}\n', }, } })() diff --git a/packages/components/__generated__/MessageItemFragment.graphql.ts b/packages/components/__generated__/MessageItemFragment.graphql.ts index ee7b1e4c..8bfffb2a 100644 --- a/packages/components/__generated__/MessageItemFragment.graphql.ts +++ b/packages/components/__generated__/MessageItemFragment.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<6d1833ac04981218b0763c0c00df00f9>> + * @generated SignedSource<<98457f1eacc573a4e2f55afe1a4060e0>> * @lightSyntaxTransform * @nogrep */ @@ -24,6 +24,7 @@ export type MessageItemFragment$data = { } | null | undefined + readonly isRead: boolean | null | undefined readonly pk: number readonly profile: | { @@ -86,6 +87,13 @@ const node: ReaderFragment = (function () { selections: v1 /*: any*/, storageKey: null, }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'isRead', + storageKey: null, + }, { alias: null, args: null, @@ -116,6 +124,6 @@ const node: ReaderFragment = (function () { } })() -;(node as any).hash = '4604c0648fefbb7d9620f96f514a43af' +;(node as any).hash = 'c4f28d75734c65a3d4e80722daecfd7e' export default node diff --git a/packages/components/__generated__/MessagesListFragment.graphql.ts b/packages/components/__generated__/MessagesListFragment.graphql.ts index 00293bf3..f94c5e4b 100644 --- a/packages/components/__generated__/MessagesListFragment.graphql.ts +++ b/packages/components/__generated__/MessagesListFragment.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<4cd4d07aa30c188f82b80c8eebe02979>> + * @generated SignedSource<<91b489da3df08f0b62ec9dce25b08a58>> * @lightSyntaxTransform * @nogrep */ @@ -20,6 +20,7 @@ export type MessagesListFragment$data = { | { readonly created: any readonly id: string + readonly isRead: boolean | null | undefined readonly profile: | { readonly id: string @@ -56,6 +57,7 @@ export type MessagesListFragment$data = { } | null | undefined + readonly unreadMessagesCount: number | null | undefined readonly ' $fragmentType': 'MessagesListFragment' } export type MessagesListFragment$key = { @@ -132,6 +134,13 @@ const node: ReaderFragment = (function () { selections: [v2 /*: any*/], storageKey: null, }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'unreadMessagesCount', + storageKey: null, + }, { alias: 'allMessages', args: null, @@ -213,6 +222,13 @@ const node: ReaderFragment = (function () { ], storageKey: null, }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'isRead', + storageKey: null, + }, { args: null, kind: 'FragmentSpread', @@ -272,6 +288,6 @@ const node: ReaderFragment = (function () { } })() -;(node as any).hash = '140657eaa254ee3833f86c73b44cc05a' +;(node as any).hash = '1eebe2365c138d57d71fb4d1365102b9' export default node diff --git a/packages/components/__generated__/ProfileItemFragment.graphql.ts b/packages/components/__generated__/ProfileItemFragment.graphql.ts index d27f353f..78be7cd9 100644 --- a/packages/components/__generated__/ProfileItemFragment.graphql.ts +++ b/packages/components/__generated__/ProfileItemFragment.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<2508af9152fbd3e4b88dbe1d97748cf0>> + * @generated SignedSource<> * @lightSyntaxTransform * @nogrep */ @@ -8,7 +8,7 @@ /* eslint-disable */ // @ts-nocheck -import { InlineFragment, ReaderInlineDataFragment } from 'relay-runtime' +import { Fragment, ReaderFragment } from 'relay-runtime' import { FragmentRefs } from 'relay-runtime' export type ProfileItemFragment$data = { @@ -33,11 +33,84 @@ export type ProfileItemFragment$key = { readonly ' $fragmentSpreads': FragmentRefs<'ProfileItemFragment'> } -const node: ReaderInlineDataFragment = { - kind: 'InlineDataFragment', +const node: ReaderFragment = { + argumentDefinitions: [ + { + defaultValue: 100, + kind: 'LocalArgument', + name: 'avatarSize', + }, + ], + kind: 'Fragment', + metadata: null, name: 'ProfileItemFragment', + selections: [ + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'id', + storageKey: null, + }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'name', + storageKey: null, + }, + { + alias: null, + args: [ + { + kind: 'Variable', + name: 'height', + variableName: 'avatarSize', + }, + { + kind: 'Variable', + name: 'width', + variableName: 'avatarSize', + }, + ], + concreteType: 'File', + kind: 'LinkedField', + name: 'image', + plural: false, + selections: [ + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'url', + storageKey: null, + }, + ], + storageKey: null, + }, + { + alias: null, + args: null, + concreteType: 'URLPath', + kind: 'LinkedField', + name: 'urlPath', + plural: false, + selections: [ + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'path', + storageKey: null, + }, + ], + storageKey: null, + }, + ], + type: 'Profile', + abstractKey: null, } -;(node as any).hash = '4ff01a864028d7fc90c536a46839d28f' +;(node as any).hash = 'b32115278ad65ec9a310b97d23b5c85b' export default node diff --git a/packages/components/__generated__/ProfileItemInlineFragment.graphql.ts b/packages/components/__generated__/ProfileItemInlineFragment.graphql.ts new file mode 100644 index 00000000..960ba882 --- /dev/null +++ b/packages/components/__generated__/ProfileItemInlineFragment.graphql.ts @@ -0,0 +1,43 @@ +/** + * @generated SignedSource<<5ce5cc227ff15da2da614055efdf35e6>> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ + +/* eslint-disable */ +// @ts-nocheck +import { InlineFragment, ReaderInlineDataFragment } from 'relay-runtime' +import { FragmentRefs } from 'relay-runtime' + +export type ProfileItemInlineFragment$data = { + readonly id: string + readonly image: + | { + readonly url: string + } + | null + | undefined + readonly name: string | null | undefined + readonly urlPath: + | { + readonly path: string + } + | null + | undefined + readonly ' $fragmentType': 'ProfileItemInlineFragment' +} +export type ProfileItemInlineFragment$key = { + readonly ' $data'?: ProfileItemInlineFragment$data + readonly ' $fragmentSpreads': FragmentRefs<'ProfileItemInlineFragment'> +} + +const node: ReaderInlineDataFragment = { + kind: 'InlineDataFragment', + name: 'ProfileItemInlineFragment', +} + +;(node as any).hash = '3a57d843aa0456e03512fcd980504f41' + +export default node diff --git a/packages/components/__generated__/ProfilesListQuery.graphql.ts b/packages/components/__generated__/ProfilesListQuery.graphql.ts index 033e0282..14719c0a 100644 --- a/packages/components/__generated__/ProfilesListQuery.graphql.ts +++ b/packages/components/__generated__/ProfilesListQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<29dd7fcd5910c311d1ab1ac81ecbbb6c>> + * @generated SignedSource<<5f1b4c7974ce16c3ce1eff8e23f1c2a6>> * @lightSyntaxTransform * @nogrep */ @@ -18,7 +18,7 @@ export type ProfilesListQuery$data = { readonly profiles: | ReadonlyArray< | { - readonly ' $fragmentSpreads': FragmentRefs<'ProfileItemFragment'> + readonly ' $fragmentSpreads': FragmentRefs<'ProfileItemInlineFragment'> } | null | undefined @@ -90,7 +90,7 @@ const node: ConcreteRequest = (function () { selections: [ { kind: 'InlineDataFragmentSpread', - name: 'ProfileItemFragment', + name: 'ProfileItemInlineFragment', selections: [ v0 /*: any*/, v1 /*: any*/, @@ -210,16 +210,16 @@ const node: ConcreteRequest = (function () { ], }, params: { - cacheID: 'f45449b4beffd5247f8dd3fcb75e43cd', + cacheID: '52d75d6be606957b650bc2b8ef5c5abf', id: null, metadata: {}, name: 'ProfilesListQuery', operationKind: 'query', - text: 'query ProfilesListQuery {\n me {\n profiles {\n ...ProfileItemFragment\n id\n }\n id\n }\n}\n\nfragment ProfileItemFragment on Profile {\n id\n name\n image(width: 100, height: 100) {\n url\n }\n urlPath {\n path\n id\n }\n}\n', + text: 'query ProfilesListQuery {\n me {\n profiles {\n ...ProfileItemInlineFragment\n id\n }\n id\n }\n}\n\nfragment ProfileItemInlineFragment on Profile {\n id\n name\n image(width: 100, height: 100) {\n url\n }\n urlPath {\n path\n id\n }\n}\n', }, } })() -;(node as any).hash = 'ce9ca315be07ccdb58629abb177bc931' +;(node as any).hash = 'e33762cabf29142fa4a43f70fa2f0640' export default node diff --git a/packages/components/__generated__/ReadMessagesMutation.graphql.ts b/packages/components/__generated__/ReadMessagesMutation.graphql.ts new file mode 100644 index 00000000..8a040bd2 --- /dev/null +++ b/packages/components/__generated__/ReadMessagesMutation.graphql.ts @@ -0,0 +1,487 @@ +/** + * @generated SignedSource<<52d5b4ddfcd9386fc78d0b20b872c96c>> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ + +/* eslint-disable */ +// @ts-nocheck +import { ConcreteRequest, Mutation } from 'relay-runtime' +import { FragmentRefs } from 'relay-runtime' + +export type ChatRoomReadMessagesInput = { + clientMutationId?: string | null | undefined + messageIds?: ReadonlyArray | null | undefined + profileId: string + roomId: string +} +export type ReadMessagesMutation$variables = { + input: ChatRoomReadMessagesInput +} +export type ReadMessagesMutation$data = { + readonly chatRoomReadMessages: + | { + readonly errors: + | ReadonlyArray< + | { + readonly field: string + readonly messages: ReadonlyArray + } + | null + | undefined + > + | null + | undefined + readonly room: + | { + readonly id: string + readonly unreadMessagesCount: number | null | undefined + readonly ' $fragmentSpreads': FragmentRefs<'RoomFragment'> + } + | null + | undefined + } + | null + | undefined +} +export type ReadMessagesMutation = { + response: ReadMessagesMutation$data + variables: ReadMessagesMutation$variables +} + +const node: ConcreteRequest = (function () { + var v0 = [ + { + defaultValue: null, + kind: 'LocalArgument', + name: 'input', + }, + ], + v1 = [ + { + kind: 'Variable', + name: 'input', + variableName: 'input', + }, + ], + v2 = { + alias: null, + args: null, + kind: 'ScalarField', + name: 'id', + storageKey: null, + }, + v3 = { + alias: null, + args: null, + kind: 'ScalarField', + name: 'unreadMessagesCount', + storageKey: null, + }, + v4 = { + alias: null, + args: null, + concreteType: 'ErrorType', + kind: 'LinkedField', + name: 'errors', + plural: true, + selections: [ + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'field', + storageKey: null, + }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'messages', + storageKey: null, + }, + ], + storageKey: null, + }, + v5 = [ + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'url', + storageKey: null, + }, + ], + v6 = { + alias: null, + args: [ + { + kind: 'Literal', + name: 'height', + value: 100, + }, + { + kind: 'Literal', + name: 'width', + value: 100, + }, + ], + concreteType: 'File', + kind: 'LinkedField', + name: 'image', + plural: false, + selections: v5 /*: any*/, + storageKey: 'image(height:100,width:100)', + }, + v7 = { + alias: null, + args: null, + kind: 'ScalarField', + name: 'content', + storageKey: null, + }, + v8 = { + alias: null, + args: null, + kind: 'ScalarField', + name: 'totalCount', + storageKey: null, + }, + v9 = { + alias: null, + args: null, + kind: 'ScalarField', + name: '__typename', + storageKey: null, + }, + v10 = { + alias: null, + args: null, + kind: 'ScalarField', + name: 'name', + storageKey: null, + }, + v11 = [ + { + kind: 'Literal', + name: 'first', + value: 20, + }, + ] + return { + fragment: { + argumentDefinitions: v0 /*: any*/, + kind: 'Fragment', + metadata: null, + name: 'ReadMessagesMutation', + selections: [ + { + alias: null, + args: v1 /*: any*/, + concreteType: 'ChatRoomReadMessagesPayload', + kind: 'LinkedField', + name: 'chatRoomReadMessages', + plural: false, + selections: [ + { + alias: null, + args: null, + concreteType: 'ChatRoom', + kind: 'LinkedField', + name: 'room', + plural: false, + selections: [ + v2 /*: any*/, + v3 /*: any*/, + { + args: null, + kind: 'FragmentSpread', + name: 'RoomFragment', + }, + ], + storageKey: null, + }, + v4 /*: any*/, + ], + storageKey: null, + }, + ], + type: 'Mutation', + abstractKey: null, + }, + kind: 'Request', + operation: { + argumentDefinitions: v0 /*: any*/, + kind: 'Operation', + name: 'ReadMessagesMutation', + selections: [ + { + alias: null, + args: v1 /*: any*/, + concreteType: 'ChatRoomReadMessagesPayload', + kind: 'LinkedField', + name: 'chatRoomReadMessages', + plural: false, + selections: [ + { + alias: null, + args: null, + concreteType: 'ChatRoom', + kind: 'LinkedField', + name: 'room', + plural: false, + selections: [ + v2 /*: any*/, + v3 /*: any*/, + v6 /*: any*/, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'lastMessageTime', + storageKey: null, + }, + { + alias: null, + args: null, + concreteType: 'Message', + kind: 'LinkedField', + name: 'lastMessage', + plural: false, + selections: [v2 /*: any*/, v7 /*: any*/], + storageKey: null, + }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'title', + storageKey: null, + }, + { + alias: null, + args: null, + concreteType: 'ChatRoomParticipantConnection', + kind: 'LinkedField', + name: 'participants', + plural: false, + selections: [ + v8 /*: any*/, + { + alias: null, + args: null, + concreteType: 'ChatRoomParticipantEdge', + kind: 'LinkedField', + name: 'edges', + plural: true, + selections: [ + { + alias: null, + args: null, + concreteType: 'ChatRoomParticipant', + kind: 'LinkedField', + name: 'node', + plural: false, + selections: [ + v2 /*: any*/, + { + alias: null, + args: null, + concreteType: 'Profile', + kind: 'LinkedField', + name: 'profile', + plural: false, + selections: [v2 /*: any*/, v9 /*: any*/, v10 /*: any*/, v6 /*: any*/], + storageKey: null, + }, + ], + storageKey: null, + }, + ], + storageKey: null, + }, + ], + storageKey: null, + }, + { + alias: null, + args: v11 /*: any*/, + concreteType: 'MessageConnection', + kind: 'LinkedField', + name: 'allMessages', + plural: false, + selections: [ + v8 /*: any*/, + { + alias: null, + args: null, + concreteType: 'MessageEdge', + kind: 'LinkedField', + name: 'edges', + plural: true, + selections: [ + { + alias: null, + args: null, + concreteType: 'Message', + kind: 'LinkedField', + name: 'node', + plural: false, + selections: [ + v2 /*: any*/, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'created', + storageKey: null, + }, + { + alias: null, + args: null, + concreteType: 'Profile', + kind: 'LinkedField', + name: 'profile', + plural: false, + selections: [ + v2 /*: any*/, + v10 /*: any*/, + { + alias: null, + args: [ + { + kind: 'Literal', + name: 'height', + value: 32, + }, + { + kind: 'Literal', + name: 'width', + value: 32, + }, + ], + concreteType: 'File', + kind: 'LinkedField', + name: 'image', + plural: false, + selections: v5 /*: any*/, + storageKey: 'image(height:32,width:32)', + }, + ], + storageKey: null, + }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'isRead', + storageKey: null, + }, + v7 /*: any*/, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'extraData', + storageKey: null, + }, + { + alias: null, + args: null, + concreteType: 'Message', + kind: 'LinkedField', + name: 'inReplyTo', + plural: false, + selections: [v2 /*: any*/], + storageKey: null, + }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'pk', + storageKey: null, + }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'verb', + storageKey: null, + }, + v9 /*: any*/, + ], + storageKey: null, + }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'cursor', + storageKey: null, + }, + ], + storageKey: null, + }, + { + alias: null, + args: null, + concreteType: 'PageInfo', + kind: 'LinkedField', + name: 'pageInfo', + plural: false, + selections: [ + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'hasNextPage', + storageKey: null, + }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'endCursor', + storageKey: null, + }, + ], + storageKey: null, + }, + ], + storageKey: 'allMessages(first:20)', + }, + { + alias: null, + args: v11 /*: any*/, + filters: null, + handle: 'connection', + key: 'chatRoom_allMessages', + kind: 'LinkedHandle', + name: 'allMessages', + }, + ], + storageKey: null, + }, + v4 /*: any*/, + ], + storageKey: null, + }, + ], + }, + params: { + cacheID: '17d51112d5e90700cfa7dd3027f2e4b2', + id: null, + metadata: {}, + name: 'ReadMessagesMutation', + operationKind: 'mutation', + text: 'mutation ReadMessagesMutation(\n $input: ChatRoomReadMessagesInput!\n) {\n chatRoomReadMessages(input: $input) {\n room {\n id\n unreadMessagesCount\n ...RoomFragment\n }\n errors {\n field\n messages\n }\n }\n}\n\nfragment MessageItemFragment on Message {\n id\n content\n created\n extraData\n inReplyTo {\n id\n }\n isRead\n pk\n profile {\n id\n }\n verb\n}\n\nfragment MessagesListFragment on ChatRoom {\n id\n participants {\n totalCount\n }\n unreadMessagesCount\n allMessages(first: 20) {\n totalCount\n edges {\n node {\n id\n created\n profile {\n id\n name\n image(height: 32, width: 32) {\n url\n }\n }\n isRead\n ...MessageItemFragment\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n}\n\nfragment RoomFragment on ChatRoom {\n id\n unreadMessagesCount\n image(width: 100, height: 100) {\n url\n }\n lastMessageTime\n lastMessage {\n id\n content\n }\n title\n participants {\n totalCount\n edges {\n node {\n id\n profile {\n id\n __typename\n name\n image(width: 100, height: 100) {\n url\n }\n }\n }\n }\n }\n ...MessagesListFragment\n}\n', + }, + } +})() + +;(node as any).hash = '5e16432139531f48bfb558baf5270f82' + +export default node diff --git a/packages/components/__generated__/RoomsListFragment.graphql.ts b/packages/components/__generated__/RoomsListFragment.graphql.ts index 59d21bc7..6290dfa2 100644 --- a/packages/components/__generated__/RoomsListFragment.graphql.ts +++ b/packages/components/__generated__/RoomsListFragment.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<> * @lightSyntaxTransform * @nogrep */ @@ -77,6 +77,11 @@ const node: ReaderFragment = (function () { kind: 'LocalArgument', name: 'q', }, + { + defaultValue: false, + kind: 'LocalArgument', + name: 'unreadMessages', + }, ], kind: 'Fragment', metadata: { @@ -108,6 +113,7 @@ const node: ReaderFragment = (function () { name: 'RoomsListFragment', selections: [ v1 /*: any*/, + v2 /*: any*/, { alias: 'chatRooms', args: [ @@ -116,6 +122,11 @@ const node: ReaderFragment = (function () { name: 'q', variableName: 'q', }, + { + kind: 'Variable', + name: 'unreadMessages', + variableName: 'unreadMessages', + }, ], concreteType: 'ChatRoomConnection', kind: 'LinkedField', @@ -193,13 +204,12 @@ const node: ReaderFragment = (function () { ], storageKey: null, }, - v2 /*: any*/, ], type: 'ChatRoomsInterface', abstractKey: '__isChatRoomsInterface', } })() -;(node as any).hash = '503f16e1be2d090bcacfff6d0c023a45' +;(node as any).hash = 'cf8dd10e5de039944535e8c431f1adfb' export default node diff --git a/packages/components/__generated__/SendMessageMutation.graphql.ts b/packages/components/__generated__/SendMessageMutation.graphql.ts index 79eaef5a..4ac8e316 100644 --- a/packages/components/__generated__/SendMessageMutation.graphql.ts +++ b/packages/components/__generated__/SendMessageMutation.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<850d8d2b6162ef90880d0b8d4c29025e>> + * @generated SignedSource<<02cc7cf8caa3d796e42f687781773bfc>> * @lightSyntaxTransform * @nogrep */ @@ -221,6 +221,13 @@ const node: ConcreteRequest = (function () { selections: v5 /*: any*/, storageKey: null, }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'isRead', + storageKey: null, + }, { alias: null, args: null, @@ -274,12 +281,12 @@ const node: ConcreteRequest = (function () { ], }, params: { - cacheID: '1838c3c055734b92abd6548a0b70caac', + cacheID: '1d655e68797f0439e7ca317168d662ce', id: null, metadata: {}, name: 'SendMessageMutation', operationKind: 'mutation', - text: 'mutation SendMessageMutation(\n $input: ChatRoomSendMessageInput!\n) {\n chatRoomSendMessage(input: $input) {\n message {\n node {\n id\n ...MessageItemFragment\n }\n }\n errors {\n field\n messages\n }\n }\n}\n\nfragment MessageItemFragment on Message {\n id\n content\n created\n extraData\n inReplyTo {\n id\n }\n pk\n profile {\n id\n }\n verb\n}\n', + text: 'mutation SendMessageMutation(\n $input: ChatRoomSendMessageInput!\n) {\n chatRoomSendMessage(input: $input) {\n message {\n node {\n id\n ...MessageItemFragment\n }\n }\n errors {\n field\n messages\n }\n }\n}\n\nfragment MessageItemFragment on Message {\n id\n content\n created\n extraData\n inReplyTo {\n id\n }\n isRead\n pk\n profile {\n id\n }\n verb\n}\n', }, } })() diff --git a/packages/components/__generated__/UserProfileQuery.graphql.ts b/packages/components/__generated__/UserProfileQuery.graphql.ts index 2f6e42fb..7ffcd471 100644 --- a/packages/components/__generated__/UserProfileQuery.graphql.ts +++ b/packages/components/__generated__/UserProfileQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<862e9f95a1e50f0c861f2b8878f34e3b>> + * @generated SignedSource<> * @lightSyntaxTransform * @nogrep */ @@ -17,7 +17,7 @@ export type UserProfileQuery$data = { | { readonly profile: | { - readonly ' $fragmentSpreads': FragmentRefs<'ProfileItemFragment'> + readonly ' $fragmentSpreads': FragmentRefs<'ProfileItemInlineFragment'> } | null | undefined @@ -86,7 +86,7 @@ const node: ConcreteRequest = (function () { selections: [ { kind: 'InlineDataFragmentSpread', - name: 'ProfileItemFragment', + name: 'ProfileItemInlineFragment', selections: [ v0 /*: any*/, v1 /*: any*/, @@ -206,16 +206,16 @@ const node: ConcreteRequest = (function () { ], }, params: { - cacheID: '4a09b56bb39794e18b189981877fa031', + cacheID: 'a85f1b3f866dce00c22e0195d8f91a9a', id: null, metadata: {}, name: 'UserProfileQuery', operationKind: 'query', - text: 'query UserProfileQuery {\n me {\n profile {\n ...ProfileItemFragment\n id\n }\n id\n }\n}\n\nfragment ProfileItemFragment on Profile {\n id\n name\n image(width: 100, height: 100) {\n url\n }\n urlPath {\n path\n id\n }\n}\n', + text: 'query UserProfileQuery {\n me {\n profile {\n ...ProfileItemInlineFragment\n id\n }\n id\n }\n}\n\nfragment ProfileItemInlineFragment on Profile {\n id\n name\n image(width: 100, height: 100) {\n url\n }\n urlPath {\n path\n id\n }\n}\n', }, } })() -;(node as any).hash = '8febc9fbb812c3456d12d0ff6a69c90a' +;(node as any).hash = 'fe5b9485e3ef19ae48b2142a3c72c7f7' export default node diff --git a/packages/components/__generated__/chatRoomsPaginationQuery.graphql.ts b/packages/components/__generated__/chatRoomsPaginationQuery.graphql.ts index c62dbe54..78d2c159 100644 --- a/packages/components/__generated__/chatRoomsPaginationQuery.graphql.ts +++ b/packages/components/__generated__/chatRoomsPaginationQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<90594853ede98080a5f45b3437de98c7>> + * @generated SignedSource<<0da3b8f334193df5e7fb534994876c50>> * @lightSyntaxTransform * @nogrep */ @@ -16,6 +16,7 @@ export type chatRoomsPaginationQuery$variables = { cursor?: string | null | undefined id: string q?: string | null | undefined + unreadMessages?: boolean | null | undefined } export type chatRoomsPaginationQuery$data = { readonly node: @@ -51,33 +52,50 @@ const node: ConcreteRequest = (function () { kind: 'LocalArgument', name: 'q', }, - v4 = [ + v4 = { + defaultValue: false, + kind: 'LocalArgument', + name: 'unreadMessages', + }, + v5 = [ { kind: 'Variable', name: 'id', variableName: 'id', }, ], - v5 = { + v6 = { kind: 'Variable', name: 'q', variableName: 'q', }, - v6 = { + v7 = { + kind: 'Variable', + name: 'unreadMessages', + variableName: 'unreadMessages', + }, + v8 = { alias: null, args: null, kind: 'ScalarField', name: '__typename', storageKey: null, }, - v7 = { + v9 = { alias: null, args: null, kind: 'ScalarField', name: 'id', storageKey: null, }, - v8 = [ + v10 = { + alias: null, + args: null, + kind: 'ScalarField', + name: 'unreadMessagesCount', + storageKey: null, + }, + v11 = [ { kind: 'Variable', name: 'after', @@ -88,16 +106,10 @@ const node: ConcreteRequest = (function () { name: 'first', variableName: 'count', }, - v5 /*: any*/, + v6 /*: any*/, + v7 /*: any*/, ], - v9 = { - alias: null, - args: null, - kind: 'ScalarField', - name: 'unreadMessagesCount', - storageKey: null, - }, - v10 = [ + v12 = [ { alias: null, args: null, @@ -106,7 +118,7 @@ const node: ConcreteRequest = (function () { storageKey: null, }, ], - v11 = { + v13 = { alias: null, args: [ { @@ -124,45 +136,45 @@ const node: ConcreteRequest = (function () { kind: 'LinkedField', name: 'image', plural: false, - selections: v10 /*: any*/, + selections: v12 /*: any*/, storageKey: 'image(height:100,width:100)', }, - v12 = { + v14 = { alias: null, args: null, kind: 'ScalarField', name: 'content', storageKey: null, }, - v13 = { + v15 = { alias: null, args: null, kind: 'ScalarField', name: 'totalCount', storageKey: null, }, - v14 = { + v16 = { alias: null, args: null, kind: 'ScalarField', name: 'name', storageKey: null, }, - v15 = [ + v17 = [ { kind: 'Literal', name: 'first', value: 20, }, ], - v16 = { + v18 = { alias: null, args: null, kind: 'ScalarField', name: 'cursor', storageKey: null, }, - v17 = { + v19 = { alias: null, args: null, concreteType: 'PageInfo', @@ -189,14 +201,14 @@ const node: ConcreteRequest = (function () { } return { fragment: { - argumentDefinitions: [v0 /*: any*/, v1 /*: any*/, v2 /*: any*/, v3 /*: any*/], + argumentDefinitions: [v0 /*: any*/, v1 /*: any*/, v2 /*: any*/, v3 /*: any*/, v4 /*: any*/], kind: 'Fragment', metadata: null, name: 'chatRoomsPaginationQuery', selections: [ { alias: null, - args: v4 /*: any*/, + args: v5 /*: any*/, concreteType: null, kind: 'LinkedField', name: 'node', @@ -214,7 +226,8 @@ const node: ConcreteRequest = (function () { name: 'cursor', variableName: 'cursor', }, - v5 /*: any*/, + v6 /*: any*/, + v7 /*: any*/, ], kind: 'FragmentSpread', name: 'RoomsListFragment', @@ -228,26 +241,27 @@ const node: ConcreteRequest = (function () { }, kind: 'Request', operation: { - argumentDefinitions: [v0 /*: any*/, v1 /*: any*/, v3 /*: any*/, v2 /*: any*/], + argumentDefinitions: [v0 /*: any*/, v1 /*: any*/, v3 /*: any*/, v4 /*: any*/, v2 /*: any*/], kind: 'Operation', name: 'chatRoomsPaginationQuery', selections: [ { alias: null, - args: v4 /*: any*/, + args: v5 /*: any*/, concreteType: null, kind: 'LinkedField', name: 'node', plural: false, selections: [ - v6 /*: any*/, - v7 /*: any*/, + v8 /*: any*/, + v9 /*: any*/, { kind: 'InlineFragment', selections: [ + v10 /*: any*/, { alias: null, - args: v8 /*: any*/, + args: v11 /*: any*/, concreteType: 'ChatRoomConnection', kind: 'LinkedField', name: 'chatRooms', @@ -269,9 +283,9 @@ const node: ConcreteRequest = (function () { name: 'node', plural: false, selections: [ - v7 /*: any*/, v9 /*: any*/, - v11 /*: any*/, + v10 /*: any*/, + v13 /*: any*/, { alias: null, args: null, @@ -286,7 +300,7 @@ const node: ConcreteRequest = (function () { kind: 'LinkedField', name: 'lastMessage', plural: false, - selections: [v7 /*: any*/, v12 /*: any*/], + selections: [v9 /*: any*/, v14 /*: any*/], storageKey: null, }, { @@ -304,7 +318,7 @@ const node: ConcreteRequest = (function () { name: 'participants', plural: false, selections: [ - v13 /*: any*/, + v15 /*: any*/, { alias: null, args: null, @@ -321,7 +335,7 @@ const node: ConcreteRequest = (function () { name: 'node', plural: false, selections: [ - v7 /*: any*/, + v9 /*: any*/, { alias: null, args: null, @@ -330,10 +344,10 @@ const node: ConcreteRequest = (function () { name: 'profile', plural: false, selections: [ - v7 /*: any*/, - v6 /*: any*/, - v14 /*: any*/, - v11 /*: any*/, + v9 /*: any*/, + v8 /*: any*/, + v16 /*: any*/, + v13 /*: any*/, ], storageKey: null, }, @@ -348,13 +362,13 @@ const node: ConcreteRequest = (function () { }, { alias: null, - args: v15 /*: any*/, + args: v17 /*: any*/, concreteType: 'MessageConnection', kind: 'LinkedField', name: 'allMessages', plural: false, selections: [ - v13 /*: any*/, + v15 /*: any*/, { alias: null, args: null, @@ -371,7 +385,7 @@ const node: ConcreteRequest = (function () { name: 'node', plural: false, selections: [ - v7 /*: any*/, + v9 /*: any*/, { alias: null, args: null, @@ -387,8 +401,8 @@ const node: ConcreteRequest = (function () { name: 'profile', plural: false, selections: [ - v7 /*: any*/, - v14 /*: any*/, + v9 /*: any*/, + v16 /*: any*/, { alias: null, args: [ @@ -407,13 +421,20 @@ const node: ConcreteRequest = (function () { kind: 'LinkedField', name: 'image', plural: false, - selections: v10 /*: any*/, + selections: v12 /*: any*/, storageKey: 'image(height:32,width:32)', }, ], storageKey: null, }, - v12 /*: any*/, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'isRead', + storageKey: null, + }, + v14 /*: any*/, { alias: null, args: null, @@ -428,7 +449,7 @@ const node: ConcreteRequest = (function () { kind: 'LinkedField', name: 'inReplyTo', plural: false, - selections: [v7 /*: any*/], + selections: [v9 /*: any*/], storageKey: null, }, { @@ -445,49 +466,48 @@ const node: ConcreteRequest = (function () { name: 'verb', storageKey: null, }, - v6 /*: any*/, + v8 /*: any*/, ], storageKey: null, }, - v16 /*: any*/, + v18 /*: any*/, ], storageKey: null, }, - v17 /*: any*/, + v19 /*: any*/, ], storageKey: 'allMessages(first:20)', }, { alias: null, - args: v15 /*: any*/, + args: v17 /*: any*/, filters: null, handle: 'connection', key: 'chatRoom_allMessages', kind: 'LinkedHandle', name: 'allMessages', }, - v6 /*: any*/, + v8 /*: any*/, ], storageKey: null, }, - v16 /*: any*/, + v18 /*: any*/, ], storageKey: null, }, - v17 /*: any*/, + v19 /*: any*/, ], storageKey: null, }, { alias: null, - args: v8 /*: any*/, - filters: ['q'], + args: v11 /*: any*/, + filters: ['q', 'unreadMessages'], handle: 'connection', key: 'roomsList_chatRooms', kind: 'LinkedHandle', name: 'chatRooms', }, - v9 /*: any*/, ], type: 'ChatRoomsInterface', abstractKey: '__isChatRoomsInterface', @@ -498,16 +518,16 @@ const node: ConcreteRequest = (function () { ], }, params: { - cacheID: 'd2e62465c109463b6975a50af0ffa5c5', + cacheID: '2498718df6928cbf601ebbe7166e32f4', id: null, metadata: {}, name: 'chatRoomsPaginationQuery', operationKind: 'query', - text: 'query chatRoomsPaginationQuery(\n $count: Int = 5\n $cursor: String\n $q: String = null\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...RoomsListFragment_XhAmI\n id\n }\n}\n\nfragment MessageItemFragment on Message {\n id\n content\n created\n extraData\n inReplyTo {\n id\n }\n pk\n profile {\n id\n }\n verb\n}\n\nfragment MessagesListFragment on ChatRoom {\n id\n participants {\n totalCount\n }\n allMessages(first: 20) {\n totalCount\n edges {\n node {\n id\n created\n profile {\n id\n name\n image(height: 32, width: 32) {\n url\n }\n }\n ...MessageItemFragment\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n}\n\nfragment RoomFragment on ChatRoom {\n id\n unreadMessagesCount\n image(width: 100, height: 100) {\n url\n }\n lastMessageTime\n lastMessage {\n id\n content\n }\n title\n participants {\n totalCount\n edges {\n node {\n id\n profile {\n id\n __typename\n name\n image(width: 100, height: 100) {\n url\n }\n }\n }\n }\n }\n ...MessagesListFragment\n}\n\nfragment RoomsListFragment_XhAmI on ChatRoomsInterface {\n __isChatRoomsInterface: __typename\n id\n chatRooms(first: $count, after: $cursor, q: $q) {\n edges {\n node {\n id\n unreadMessagesCount\n ...RoomFragment\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n unreadMessagesCount\n}\n', + text: 'query chatRoomsPaginationQuery(\n $count: Int = 5\n $cursor: String\n $q: String = null\n $unreadMessages: Boolean = false\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...RoomsListFragment_4kOb3U\n id\n }\n}\n\nfragment MessageItemFragment on Message {\n id\n content\n created\n extraData\n inReplyTo {\n id\n }\n isRead\n pk\n profile {\n id\n }\n verb\n}\n\nfragment MessagesListFragment on ChatRoom {\n id\n participants {\n totalCount\n }\n unreadMessagesCount\n allMessages(first: 20) {\n totalCount\n edges {\n node {\n id\n created\n profile {\n id\n name\n image(height: 32, width: 32) {\n url\n }\n }\n isRead\n ...MessageItemFragment\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n}\n\nfragment RoomFragment on ChatRoom {\n id\n unreadMessagesCount\n image(width: 100, height: 100) {\n url\n }\n lastMessageTime\n lastMessage {\n id\n content\n }\n title\n participants {\n totalCount\n edges {\n node {\n id\n profile {\n id\n __typename\n name\n image(width: 100, height: 100) {\n url\n }\n }\n }\n }\n }\n ...MessagesListFragment\n}\n\nfragment RoomsListFragment_4kOb3U on ChatRoomsInterface {\n __isChatRoomsInterface: __typename\n id\n unreadMessagesCount\n chatRooms(first: $count, after: $cursor, q: $q, unreadMessages: $unreadMessages) {\n edges {\n node {\n id\n unreadMessagesCount\n ...RoomFragment\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n}\n', }, } })() -;(node as any).hash = '503f16e1be2d090bcacfff6d0c023a45' +;(node as any).hash = 'cf8dd10e5de039944535e8c431f1adfb' export default node diff --git a/packages/components/__generated__/useMessageCountUpdateSubscription.graphql.ts b/packages/components/__generated__/useMessageCountUpdateSubscription.graphql.ts new file mode 100644 index 00000000..7105d3a9 --- /dev/null +++ b/packages/components/__generated__/useMessageCountUpdateSubscription.graphql.ts @@ -0,0 +1,542 @@ +/** + * @generated SignedSource<<2599ef209ba3fbbc434d26f3c87b62ca>> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ + +/* eslint-disable */ +// @ts-nocheck +import { ConcreteRequest, GraphQLSubscription } from 'relay-runtime' +import { FragmentRefs } from 'relay-runtime' + +export type useMessageCountUpdateSubscription$variables = { + profileId: string +} +export type useMessageCountUpdateSubscription$data = { + readonly chatRoomOnMessagesCountUpdate: + | { + readonly profile: + | { + readonly chatRooms: + | { + readonly edges: ReadonlyArray< + | { + readonly node: + | { + readonly __typename: 'ChatRoom' + readonly id: string + readonly unreadMessagesCount: number | null | undefined + readonly ' $fragmentSpreads': FragmentRefs<'RoomFragment'> + } + | null + | undefined + } + | null + | undefined + > + readonly totalCount: number | null | undefined + } + | null + | undefined + readonly id: string + readonly unreadMessagesCount: number | null | undefined + } + | null + | undefined + } + | null + | undefined +} +export type useMessageCountUpdateSubscription = { + response: useMessageCountUpdateSubscription$data + variables: useMessageCountUpdateSubscription$variables +} + +const node: ConcreteRequest = (function () { + var v0 = [ + { + defaultValue: null, + kind: 'LocalArgument', + name: 'profileId', + }, + ], + v1 = [ + { + kind: 'Variable', + name: 'profileId', + variableName: 'profileId', + }, + ], + v2 = { + alias: null, + args: null, + kind: 'ScalarField', + name: 'id', + storageKey: null, + }, + v3 = { + alias: null, + args: null, + kind: 'ScalarField', + name: 'unreadMessagesCount', + storageKey: null, + }, + v4 = { + alias: null, + args: null, + kind: 'ScalarField', + name: 'totalCount', + storageKey: null, + }, + v5 = { + alias: null, + args: null, + kind: 'ScalarField', + name: '__typename', + storageKey: null, + }, + v6 = [ + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'url', + storageKey: null, + }, + ], + v7 = { + alias: null, + args: [ + { + kind: 'Literal', + name: 'height', + value: 100, + }, + { + kind: 'Literal', + name: 'width', + value: 100, + }, + ], + concreteType: 'File', + kind: 'LinkedField', + name: 'image', + plural: false, + selections: v6 /*: any*/, + storageKey: 'image(height:100,width:100)', + }, + v8 = { + alias: null, + args: null, + kind: 'ScalarField', + name: 'content', + storageKey: null, + }, + v9 = { + alias: null, + args: null, + kind: 'ScalarField', + name: 'name', + storageKey: null, + }, + v10 = [ + { + kind: 'Literal', + name: 'first', + value: 20, + }, + ] + return { + fragment: { + argumentDefinitions: v0 /*: any*/, + kind: 'Fragment', + metadata: null, + name: 'useMessageCountUpdateSubscription', + selections: [ + { + alias: null, + args: v1 /*: any*/, + concreteType: 'ChatRoomOnMessagesCountUpdate', + kind: 'LinkedField', + name: 'chatRoomOnMessagesCountUpdate', + plural: false, + selections: [ + { + alias: null, + args: null, + concreteType: 'Profile', + kind: 'LinkedField', + name: 'profile', + plural: false, + selections: [ + v2 /*: any*/, + v3 /*: any*/, + { + alias: null, + args: null, + concreteType: 'ChatRoomConnection', + kind: 'LinkedField', + name: 'chatRooms', + plural: false, + selections: [ + v4 /*: any*/, + { + alias: null, + args: null, + concreteType: 'ChatRoomEdge', + kind: 'LinkedField', + name: 'edges', + plural: true, + selections: [ + { + alias: null, + args: null, + concreteType: 'ChatRoom', + kind: 'LinkedField', + name: 'node', + plural: false, + selections: [ + v2 /*: any*/, + v5 /*: any*/, + v3 /*: any*/, + { + args: null, + kind: 'FragmentSpread', + name: 'RoomFragment', + }, + ], + storageKey: null, + }, + ], + storageKey: null, + }, + ], + storageKey: null, + }, + ], + storageKey: null, + }, + ], + storageKey: null, + }, + ], + type: 'Subscription', + abstractKey: null, + }, + kind: 'Request', + operation: { + argumentDefinitions: v0 /*: any*/, + kind: 'Operation', + name: 'useMessageCountUpdateSubscription', + selections: [ + { + alias: null, + args: v1 /*: any*/, + concreteType: 'ChatRoomOnMessagesCountUpdate', + kind: 'LinkedField', + name: 'chatRoomOnMessagesCountUpdate', + plural: false, + selections: [ + { + alias: null, + args: null, + concreteType: 'Profile', + kind: 'LinkedField', + name: 'profile', + plural: false, + selections: [ + v2 /*: any*/, + v3 /*: any*/, + { + alias: null, + args: null, + concreteType: 'ChatRoomConnection', + kind: 'LinkedField', + name: 'chatRooms', + plural: false, + selections: [ + v4 /*: any*/, + { + alias: null, + args: null, + concreteType: 'ChatRoomEdge', + kind: 'LinkedField', + name: 'edges', + plural: true, + selections: [ + { + alias: null, + args: null, + concreteType: 'ChatRoom', + kind: 'LinkedField', + name: 'node', + plural: false, + selections: [ + v2 /*: any*/, + v5 /*: any*/, + v3 /*: any*/, + v7 /*: any*/, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'lastMessageTime', + storageKey: null, + }, + { + alias: null, + args: null, + concreteType: 'Message', + kind: 'LinkedField', + name: 'lastMessage', + plural: false, + selections: [v2 /*: any*/, v8 /*: any*/], + storageKey: null, + }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'title', + storageKey: null, + }, + { + alias: null, + args: null, + concreteType: 'ChatRoomParticipantConnection', + kind: 'LinkedField', + name: 'participants', + plural: false, + selections: [ + v4 /*: any*/, + { + alias: null, + args: null, + concreteType: 'ChatRoomParticipantEdge', + kind: 'LinkedField', + name: 'edges', + plural: true, + selections: [ + { + alias: null, + args: null, + concreteType: 'ChatRoomParticipant', + kind: 'LinkedField', + name: 'node', + plural: false, + selections: [ + v2 /*: any*/, + { + alias: null, + args: null, + concreteType: 'Profile', + kind: 'LinkedField', + name: 'profile', + plural: false, + selections: [ + v2 /*: any*/, + v5 /*: any*/, + v9 /*: any*/, + v7 /*: any*/, + ], + storageKey: null, + }, + ], + storageKey: null, + }, + ], + storageKey: null, + }, + ], + storageKey: null, + }, + { + alias: null, + args: v10 /*: any*/, + concreteType: 'MessageConnection', + kind: 'LinkedField', + name: 'allMessages', + plural: false, + selections: [ + v4 /*: any*/, + { + alias: null, + args: null, + concreteType: 'MessageEdge', + kind: 'LinkedField', + name: 'edges', + plural: true, + selections: [ + { + alias: null, + args: null, + concreteType: 'Message', + kind: 'LinkedField', + name: 'node', + plural: false, + selections: [ + v2 /*: any*/, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'created', + storageKey: null, + }, + { + alias: null, + args: null, + concreteType: 'Profile', + kind: 'LinkedField', + name: 'profile', + plural: false, + selections: [ + v2 /*: any*/, + v9 /*: any*/, + { + alias: null, + args: [ + { + kind: 'Literal', + name: 'height', + value: 32, + }, + { + kind: 'Literal', + name: 'width', + value: 32, + }, + ], + concreteType: 'File', + kind: 'LinkedField', + name: 'image', + plural: false, + selections: v6 /*: any*/, + storageKey: 'image(height:32,width:32)', + }, + ], + storageKey: null, + }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'isRead', + storageKey: null, + }, + v8 /*: any*/, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'extraData', + storageKey: null, + }, + { + alias: null, + args: null, + concreteType: 'Message', + kind: 'LinkedField', + name: 'inReplyTo', + plural: false, + selections: [v2 /*: any*/], + storageKey: null, + }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'pk', + storageKey: null, + }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'verb', + storageKey: null, + }, + v5 /*: any*/, + ], + storageKey: null, + }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'cursor', + storageKey: null, + }, + ], + storageKey: null, + }, + { + alias: null, + args: null, + concreteType: 'PageInfo', + kind: 'LinkedField', + name: 'pageInfo', + plural: false, + selections: [ + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'hasNextPage', + storageKey: null, + }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'endCursor', + storageKey: null, + }, + ], + storageKey: null, + }, + ], + storageKey: 'allMessages(first:20)', + }, + { + alias: null, + args: v10 /*: any*/, + filters: null, + handle: 'connection', + key: 'chatRoom_allMessages', + kind: 'LinkedHandle', + name: 'allMessages', + }, + ], + storageKey: null, + }, + ], + storageKey: null, + }, + ], + storageKey: null, + }, + ], + storageKey: null, + }, + ], + storageKey: null, + }, + ], + }, + params: { + cacheID: 'a300524a7d6b366a4ddef0f8e692e2a5', + id: null, + metadata: {}, + name: 'useMessageCountUpdateSubscription', + operationKind: 'subscription', + text: 'subscription useMessageCountUpdateSubscription(\n $profileId: ID!\n) {\n chatRoomOnMessagesCountUpdate(profileId: $profileId) {\n profile {\n id\n unreadMessagesCount\n chatRooms {\n totalCount\n edges {\n node {\n id\n __typename\n unreadMessagesCount\n ...RoomFragment\n }\n }\n }\n }\n }\n}\n\nfragment MessageItemFragment on Message {\n id\n content\n created\n extraData\n inReplyTo {\n id\n }\n isRead\n pk\n profile {\n id\n }\n verb\n}\n\nfragment MessagesListFragment on ChatRoom {\n id\n participants {\n totalCount\n }\n unreadMessagesCount\n allMessages(first: 20) {\n totalCount\n edges {\n node {\n id\n created\n profile {\n id\n name\n image(height: 32, width: 32) {\n url\n }\n }\n isRead\n ...MessageItemFragment\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n}\n\nfragment RoomFragment on ChatRoom {\n id\n unreadMessagesCount\n image(width: 100, height: 100) {\n url\n }\n lastMessageTime\n lastMessage {\n id\n content\n }\n title\n participants {\n totalCount\n edges {\n node {\n id\n profile {\n id\n __typename\n name\n image(width: 100, height: 100) {\n url\n }\n }\n }\n }\n }\n ...MessagesListFragment\n}\n', + }, + } +})() + +;(node as any).hash = 'e23433aa9b2d395b7154b98e1503417f' + +export default node diff --git a/packages/components/__generated__/useMessagesListSubscription.graphql.ts b/packages/components/__generated__/useMessagesListSubscription.graphql.ts index d996ee3f..9706f661 100644 --- a/packages/components/__generated__/useMessagesListSubscription.graphql.ts +++ b/packages/components/__generated__/useMessagesListSubscription.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<> * @lightSyntaxTransform * @nogrep */ @@ -191,6 +191,13 @@ const node: ConcreteRequest = (function () { selections: v4 /*: any*/, storageKey: null, }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'isRead', + storageKey: null, + }, { alias: null, args: null, @@ -262,12 +269,12 @@ const node: ConcreteRequest = (function () { ], }, params: { - cacheID: 'e80a0ccb5a15d422171b18aa4708cbf1', + cacheID: '883bb43d76a5fc883f45f30697fd86db', id: null, metadata: {}, name: 'useMessagesListSubscription', operationKind: 'subscription', - text: 'subscription useMessagesListSubscription(\n $roomId: ID!\n) {\n chatRoomOnNewMessage(roomId: $roomId) {\n message {\n node {\n ...MessageItemFragment\n actionObject {\n __typename\n id\n }\n id\n }\n }\n }\n}\n\nfragment MessageItemFragment on Message {\n id\n content\n created\n extraData\n inReplyTo {\n id\n }\n pk\n profile {\n id\n }\n verb\n}\n', + text: 'subscription useMessagesListSubscription(\n $roomId: ID!\n) {\n chatRoomOnNewMessage(roomId: $roomId) {\n message {\n node {\n ...MessageItemFragment\n actionObject {\n __typename\n id\n }\n id\n }\n }\n }\n}\n\nfragment MessageItemFragment on Message {\n id\n content\n created\n extraData\n inReplyTo {\n id\n }\n isRead\n pk\n profile {\n id\n }\n verb\n}\n', }, } })() diff --git a/packages/components/modules/messages/ChatRoom/index.tsx b/packages/components/modules/messages/ChatRoom/index.tsx index 3eb616b0..ac031232 100644 --- a/packages/components/modules/messages/ChatRoom/index.tsx +++ b/packages/components/modules/messages/ChatRoom/index.tsx @@ -21,6 +21,7 @@ const ChatRoom: FC = ({ SendMessage = DefaultSendMessage, SendMessageProps = {}, }) => { + // TODO: pre load this query and instead of lazyload const { chatRoom } = useLazyLoadQuery( ChatRoomQuery, { diff --git a/packages/components/modules/messages/ChatRoom/styled.tsx b/packages/components/modules/messages/ChatRoom/styled.tsx index 59b75448..038125db 100644 --- a/packages/components/modules/messages/ChatRoom/styled.tsx +++ b/packages/components/modules/messages/ChatRoom/styled.tsx @@ -1,19 +1,21 @@ import { Box } from '@mui/material' import { alpha, styled } from '@mui/material/styles' -import { HEADER } from '../../navigations/constants' - export const ChatRoomContainer = styled(Box)(({ theme }) => ({ backgroundColor: alpha(theme.palette.grey[500], 0.12), border: `1px solid ${theme.palette.grey[200]}`, - borderRadius: 8, + borderTopLeftRadius: 0, + borderTopRightRadius: theme.spacing(2), + borderBottomLeftRadius: 0, + borderBottomRightRadius: theme.spacing(2), display: 'grid', gap: theme.spacing(2), gridTemplateRows: '1fr min-content', height: '100%', paddingLeft: theme.spacing(2), width: '100%', - [theme.breakpoints.down('lg')]: { - height: `calc(100vh - ${HEADER.H_DESKTOP}px)`, + [theme.breakpoints.down('md')]: { + borderTopRightRadius: 0, + borderBottomRightRadius: 0, }, })) diff --git a/packages/components/modules/messages/ChatRoomsList/ChatRoomCard/index.tsx b/packages/components/modules/messages/ChatRoomsList/ChatRoomItem/index.tsx similarity index 70% rename from packages/components/modules/messages/ChatRoomsList/ChatRoomCard/index.tsx rename to packages/components/modules/messages/ChatRoomsList/ChatRoomItem/index.tsx index 4f4650ee..66a4046d 100644 --- a/packages/components/modules/messages/ChatRoomsList/ChatRoomCard/index.tsx +++ b/packages/components/modules/messages/ChatRoomsList/ChatRoomItem/index.tsx @@ -2,7 +2,7 @@ import { FC, SyntheticEvent } from 'react' import { AvatarWithPlaceholder } from '@baseapp-frontend/design-system' -import { Badge as DefaultBadge, Typography } from '@mui/material' +import { Box, Badge as DefaultBadge, Typography } from '@mui/material' import { useFragment } from 'react-relay' import { RoomFragment$key } from '../../../../__generated__/RoomFragment.graphql' @@ -10,10 +10,10 @@ import { useCurrentProfile } from '../../../profiles' import { MINIMUM_AMOUNT_OF_PARTICIPANTS_TO_SHOW_ROOM_TITLE } from '../../constants' import { RoomFragment } from '../../graphql/queries/Room' import { StyledChatCard } from './styled' -import { ChatRoomCardProps } from './types' +import { ChatRoomItemProps } from './types' import { formatDate } from './utils' -const ChatRoomCard: FC = ({ +const ChatRoomItem: FC = ({ roomRef, isCardSelected = false, handleClick, @@ -58,20 +58,29 @@ const ChatRoomCard: FC = ({ showPointer={!!handleClick} > -
+ {roomData.title} -
+ {lastMessage && lastMessageTime && ( <> {formatDate(lastMessageTime)} -
+ = ({ )} -
-
-
- -
+
+ + ) } -export default ChatRoomCard +export default ChatRoomItem diff --git a/packages/components/modules/messages/ChatRoomsList/ChatRoomCard/styled.tsx b/packages/components/modules/messages/ChatRoomsList/ChatRoomItem/styled.tsx similarity index 94% rename from packages/components/modules/messages/ChatRoomsList/ChatRoomCard/styled.tsx rename to packages/components/modules/messages/ChatRoomsList/ChatRoomItem/styled.tsx index d0b04522..3cd08082 100644 --- a/packages/components/modules/messages/ChatRoomsList/ChatRoomCard/styled.tsx +++ b/packages/components/modules/messages/ChatRoomsList/ChatRoomItem/styled.tsx @@ -1,5 +1,5 @@ +import { Box, alpha } from '@mui/material' import { styled } from '@mui/material/styles' -import { Box, alpha } from '@mui/system' import { StyledChatCardProps } from './types' diff --git a/packages/components/modules/messages/ChatRoomsList/ChatRoomCard/types.ts b/packages/components/modules/messages/ChatRoomsList/ChatRoomItem/types.ts similarity index 75% rename from packages/components/modules/messages/ChatRoomsList/ChatRoomCard/types.ts rename to packages/components/modules/messages/ChatRoomsList/ChatRoomItem/types.ts index 14103d5d..d200e0bf 100644 --- a/packages/components/modules/messages/ChatRoomsList/ChatRoomCard/types.ts +++ b/packages/components/modules/messages/ChatRoomsList/ChatRoomItem/types.ts @@ -1,11 +1,10 @@ import { FC } from 'react' -import { BadgeProps } from '@mui/material' -import { BoxProps } from '@mui/system' +import type { BadgeProps, BoxProps } from '@mui/material' import { RoomFragment$key } from '../../../../__generated__/RoomFragment.graphql' -export interface ChatRoomCardProps { +export interface ChatRoomItemProps { roomRef: RoomFragment$key isCardSelected?: boolean handleClick?: () => void diff --git a/packages/components/modules/messages/ChatRoomsList/ChatRoomCard/utils.ts b/packages/components/modules/messages/ChatRoomsList/ChatRoomItem/utils.ts similarity index 100% rename from packages/components/modules/messages/ChatRoomsList/ChatRoomCard/utils.ts rename to packages/components/modules/messages/ChatRoomsList/ChatRoomItem/utils.ts diff --git a/packages/components/modules/messages/ChatRoomsList/EmptyChatRoomsState/index.tsx b/packages/components/modules/messages/ChatRoomsList/EmptyChatRoomsState/index.tsx new file mode 100644 index 00000000..8f8cf7c8 --- /dev/null +++ b/packages/components/modules/messages/ChatRoomsList/EmptyChatRoomsState/index.tsx @@ -0,0 +1,14 @@ +import { SocialMediaDiscussionImage } from '@baseapp-frontend/design-system' + +import { Box, Typography } from '@mui/material' + +const EmptyChatRoomsState = () => ( + + + + No messages to be displayed. + + +) + +export default EmptyChatRoomsState diff --git a/packages/components/modules/messages/ChatRoomsList/index.tsx b/packages/components/modules/messages/ChatRoomsList/index.tsx index 3b1b70bd..effc5a2a 100644 --- a/packages/components/modules/messages/ChatRoomsList/index.tsx +++ b/packages/components/modules/messages/ChatRoomsList/index.tsx @@ -1,76 +1,94 @@ 'use client' -import { FC, useCallback, useMemo, useState, useTransition } from 'react' +import { ChangeEventHandler, FC, useCallback, useMemo, useState, useTransition } from 'react' -import { - NoMessagesIcon as DefaultNoMessagesIcon, - Searchbar as DefaultSearchbar, - LoadingState, - useResponsive, -} from '@baseapp-frontend/design-system' +import { Searchbar as DefaultSearchbar, LoadingState } from '@baseapp-frontend/design-system' -import { Box, Tab, Tabs, Typography, useTheme } from '@mui/material' +import { Box, CircularProgress, Tab, Tabs, Typography } from '@mui/material' +import { useForm } from 'react-hook-form' import { Virtuoso } from 'react-virtuoso' import { RoomsListFragment$key } from '../../../__generated__/RoomsListFragment.graphql' -import { useCurrentProfile } from '../../profiles' +import SearchNotFoundState from '../SearchNotFoundState' import { useChatRoom } from '../context' import { useRoomsList } from '../graphql/queries/RoomsList' import useRoomListSubscription from '../graphql/subscriptions/useRoomListSubscription' -import DefaultChatRoomCard from './ChatRoomCard' +import DefaultChatRoomItem from './ChatRoomItem' +import DefaultEmptyChatRoomsState from './EmptyChatRoomsState' import { CHAT_TAB_LABEL, CHAT_TAB_VALUES } from './constants' -import { ChatRoomsListProps, ChatTabValues } from './types' +import { ChatRoomListContainer } from './styled' +import { ChatRoomNode, ChatRoomsListProps, ChatTabValues } from './types' const ChatRoomsList: FC = ({ targetRef, Searchbar = DefaultSearchbar, SearchbarProps = {}, - ChatRoomCard = DefaultChatRoomCard, - ChatRoomCardProps = {}, - NoMessagesIcon = DefaultNoMessagesIcon, - NoMessagesIconProps = {}, + ChatRoomItem = DefaultChatRoomItem, + ChatRoomItemProps = {}, + EmptyChatRoomsState = DefaultEmptyChatRoomsState, VirtuosoProps = {}, }) => { const [tab, setTab] = useState(CHAT_TAB_VALUES.active) - const { profile } = useCurrentProfile() + const [isRefetchPending, startRefetchTransition] = useTransition() const { data, loadNext, isLoadingNext, hasNext, refetch } = useRoomsList( targetRef?.me?.profile as RoomsListFragment$key, ) + const [isPending, startTransition] = useTransition() + const { control, reset, watch } = useForm({ defaultValues: { search: '' } }) + + const handleSearchChange: ChangeEventHandler = (e) => { + const value = e.target.value || '' + startTransition(() => { + refetch({ q: value }) + }) + } + + const handleSearchClear = () => { + startTransition(() => { + reset() + refetch({ q: '' }) + }) + } + const handleChange = (event: React.SyntheticEvent, newTab: string) => { setTab(newTab as ChatTabValues) + startRefetchTransition(() => { + refetch( + { unreadMessages: newTab === CHAT_TAB_VALUES.unread }, + { fetchPolicy: 'store-and-network' }, + ) + }) } - const isMobile = useResponsive('down', 'sm') - const theme = useTheme() const { id: selectedRoom, setChatRoom } = useChatRoom() - const memoizedChatRooms = useMemo( + const chatRooms = useMemo( () => data?.chatRooms?.edges?.filter((edge) => edge?.node).map((edge) => edge?.node) || [], [data?.chatRooms?.edges], ) - const renderChatCard = useCallback( - (room: any) => { + useRoomListSubscription(data.id) + + const renderItem = useCallback( + (room: ChatRoomNode) => { if (!room) return null return ( - { setChatRoom({ id: room.id }) }} - {...ChatRoomCardProps} + {...ChatRoomItemProps} /> ) }, - [selectedRoom, setChatRoom, ChatRoomCardProps, ChatRoomCard], + [selectedRoom, setChatRoom, ChatRoomItemProps, ChatRoomItem], ) - useRoomListSubscription(data?.id as string, profile?.id as string) - const renderLoadingState = () => { if (!isLoadingNext) return @@ -83,21 +101,59 @@ const ChatRoomsList: FC = ({ ) } - const [isPending, startTransition] = useTransition() + const renderTabLabel = (tabValue: ChatTabValues) => ( + + + {CHAT_TAB_LABEL[CHAT_TAB_VALUES[tabValue]]} + + {isRefetchPending && tab === tabValue && } + + ) + + const renderListContent = () => { + const emptyChatRoomsList = chatRooms.length === 0 + const searchValue = watch('search') + + if (!isPending && searchValue && emptyChatRoomsList) return + + if (!isPending && emptyChatRoomsList) return + + return ( + renderItem(item)} + style={{ scrollbarWidth: 'none' }} + components={{ + Footer: renderLoadingState, + }} + endReached={() => { + if (hasNext) { + loadNext(5) + } + }} + {...VirtuosoProps} + /> + ) + } return ( -
+ - {/* @ts-ignore TODO: Check typing */} @@ -107,48 +163,19 @@ const ChatRoomsList: FC = ({ centered variant="fullWidth" sx={{ - paddingX: isMobile ? 0 : theme.spacing(2.5), - paddingTop: theme.spacing(2), + paddingX: { + xs: 0, + sm: 2.5, + }, + paddingTop: 2, }} > - - - + + + -
- {memoizedChatRooms.length === 0 ? ( - - - - No messages to be displayed. - - - ) : ( - renderChatCard(item)} - style={{ scrollbarWidth: 'none' }} - components={{ - Footer: renderLoadingState, - }} - endReached={() => { - if (hasNext) { - loadNext(5) - } - }} - {...VirtuosoProps} - /> - )} -
-
+ {renderListContent()} + ) } diff --git a/packages/components/modules/messages/ChatRoomsList/styled.tsx b/packages/components/modules/messages/ChatRoomsList/styled.tsx new file mode 100644 index 00000000..5e101bbb --- /dev/null +++ b/packages/components/modules/messages/ChatRoomsList/styled.tsx @@ -0,0 +1,9 @@ +import { Box } from '@mui/material' +import { styled } from '@mui/material/styles' + +export const ChatRoomListContainer = styled(Box)(() => ({ + display: 'grid', + gridTemplateRows: 'min-content min-content auto', + height: '100%', + width: '100%', +})) diff --git a/packages/components/modules/messages/ChatRoomsList/types.ts b/packages/components/modules/messages/ChatRoomsList/types.ts index 0febf45c..2fac7a99 100644 --- a/packages/components/modules/messages/ChatRoomsList/types.ts +++ b/packages/components/modules/messages/ChatRoomsList/types.ts @@ -3,21 +3,24 @@ import { FC } from 'react' import { SearchbarProps } from '@baseapp-frontend/design-system' import { ValueOf } from '@baseapp-frontend/utils' -import { SvgIconProps } from '@mui/material' import { VirtuosoProps } from 'react-virtuoso' import { ChatRoomsQuery$data } from '../../../__generated__/ChatRoomsQuery.graphql' -import { ChatRoomCardProps } from './ChatRoomCard/types' +import { RoomsListFragment$data } from '../../../__generated__/RoomsListFragment.graphql' +import { ChatRoomItemProps } from './ChatRoomItem/types' import { CHAT_TAB_VALUES } from './constants' +type ChatRooms = NonNullable +type ChatRoomsEdges = ChatRooms['edges'] +export type ChatRoomNode = NonNullable['node'] + export interface ChatRoomsListProps { targetRef: ChatRoomsQuery$data Searchbar?: FC SearchbarProps?: Partial - ChatRoomCard?: FC - ChatRoomCardProps?: Partial - NoMessagesIcon?: FC - NoMessagesIconProps?: Partial + ChatRoomItem?: FC + ChatRoomItemProps?: Partial + EmptyChatRoomsState?: FC VirtuosoProps?: Partial> } diff --git a/packages/components/modules/messages/CreateChatRoomList/ChatRoomListCard/types.ts b/packages/components/modules/messages/CreateChatRoomList/ChatRoomListCard/types.ts deleted file mode 100644 index ab77fa28..00000000 --- a/packages/components/modules/messages/CreateChatRoomList/ChatRoomListCard/types.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Dispatch, SetStateAction } from 'react' - -import { Disposable, UseMutationConfig } from 'react-relay' - -import { CreateChatRoomMutation } from '../../../../__generated__/CreateChatRoomMutation.graphql' -import { UseCurrentProfile } from '../../../profiles/context/CurrentProfileProvider/types' - -export interface ChatRoomListCardProps { - item: any - setIsInExistingChatRoomsView: Dispatch> - isMutationInFlight: boolean - commit: (config: UseMutationConfig) => Disposable - currentProfile: UseCurrentProfile -} diff --git a/packages/components/modules/messages/CreateChatRoomList/ChatRoomListCard/index.tsx b/packages/components/modules/messages/CreateChatRoomList/ChatRoomListItem/index.tsx similarity index 60% rename from packages/components/modules/messages/CreateChatRoomList/ChatRoomListCard/index.tsx rename to packages/components/modules/messages/CreateChatRoomList/ChatRoomListItem/index.tsx index febc353d..af567215 100644 --- a/packages/components/modules/messages/CreateChatRoomList/ChatRoomListCard/index.tsx +++ b/packages/components/modules/messages/CreateChatRoomList/ChatRoomListItem/index.tsx @@ -3,28 +3,30 @@ import { FC } from 'react' import { AvatarWithPlaceholder } from '@baseapp-frontend/design-system' -import { joinWithSeparator } from '@baseapp-frontend/utils' import { LoadingButton } from '@mui/lab' import { Box, Typography } from '@mui/material' +import { useFragment } from 'react-relay' +import { useCurrentProfile } from '../../../profiles' +import { ProfileItemFragment } from '../../../profiles/graphql/queries/ProfileItem' import { useChatRoom } from '../../context' +import { useCreateChatRoomMutation } from '../../graphql/mutations/CreateChatRoom' import { MainContainer } from './styled' -import { ChatRoomListCardProps } from './types' +import { ChatRoomListItemProps } from './types' -const ChatRoomListCard: FC = ({ - item, +const ChatRoomListItem: FC = ({ + profile: profileRef, setIsInExistingChatRoomsView, - currentProfile, - commit, - isMutationInFlight, }) => { - const { id, image, name, urlPath } = item + const { id, image, name, urlPath } = useFragment(ProfileItemFragment, profileRef) + const [commit, isMutationInFlight] = useCreateChatRoomMutation() + const { profile: currentProfile } = useCurrentProfile() const { setChatRoom } = useChatRoom() return ( - + = ({ {name} - {joinWithSeparator(['@', urlPath?.path], { separator: '' })} + {urlPath?.path && `@${urlPath.path}`} { - if (currentProfile?.profile?.id) { + if (currentProfile?.id) { commit({ variables: { - input: { profileId: currentProfile.profile.id, participants: [id] }, + input: { profileId: currentProfile.id, participants: [id] }, }, onCompleted: (data) => { setChatRoom({ id: data?.chatRoomCreate?.room?.node?.id }) @@ -62,4 +65,4 @@ const ChatRoomListCard: FC = ({ ) } -export default ChatRoomListCard +export default ChatRoomListItem diff --git a/packages/components/modules/messages/CreateChatRoomList/ChatRoomListCard/styled.tsx b/packages/components/modules/messages/CreateChatRoomList/ChatRoomListItem/styled.tsx similarity index 95% rename from packages/components/modules/messages/CreateChatRoomList/ChatRoomListCard/styled.tsx rename to packages/components/modules/messages/CreateChatRoomList/ChatRoomListItem/styled.tsx index fac532d9..a9a761b6 100644 --- a/packages/components/modules/messages/CreateChatRoomList/ChatRoomListCard/styled.tsx +++ b/packages/components/modules/messages/CreateChatRoomList/ChatRoomListItem/styled.tsx @@ -2,6 +2,7 @@ import { Box } from '@mui/material' import { styled } from '@mui/material/styles' export const MainContainer = styled(Box)(({ theme }) => ({ + alignItems: 'center', display: 'grid', width: '100%', height: '100%', diff --git a/packages/components/modules/messages/CreateChatRoomList/ChatRoomListItem/types.ts b/packages/components/modules/messages/CreateChatRoomList/ChatRoomListItem/types.ts new file mode 100644 index 00000000..55c6cba6 --- /dev/null +++ b/packages/components/modules/messages/CreateChatRoomList/ChatRoomListItem/types.ts @@ -0,0 +1,8 @@ +import { Dispatch, SetStateAction } from 'react' + +import { ProfileItemFragment$key } from '../../../../__generated__/ProfileItemFragment.graphql' + +export interface ChatRoomListItemProps { + profile: ProfileItemFragment$key + setIsInExistingChatRoomsView: Dispatch> +} diff --git a/packages/components/modules/messages/CreateChatRoomList/EmptyProfilesListState/index.tsx b/packages/components/modules/messages/CreateChatRoomList/EmptyProfilesListState/index.tsx new file mode 100644 index 00000000..9f8a9863 --- /dev/null +++ b/packages/components/modules/messages/CreateChatRoomList/EmptyProfilesListState/index.tsx @@ -0,0 +1,19 @@ +import { WeAreHiringImage } from '@baseapp-frontend/design-system' + +import { Box, Typography } from '@mui/material' + +const EmptyProfilesListState = () => ( + + + + + Search for profiles + + + Once you connect to other profiles they will be shown here. + + + +) + +export default EmptyProfilesListState diff --git a/packages/components/modules/messages/CreateChatRoomList/index.tsx b/packages/components/modules/messages/CreateChatRoomList/index.tsx index 0a18613b..f8cf7f1b 100644 --- a/packages/components/modules/messages/CreateChatRoomList/index.tsx +++ b/packages/components/modules/messages/CreateChatRoomList/index.tsx @@ -1,6 +1,6 @@ 'use client' -import { FC, useMemo, useTransition } from 'react' +import { ChangeEventHandler, FC, useMemo, useTransition } from 'react' import { AvatarWithPlaceholder, @@ -8,26 +8,22 @@ import { LoadingState, } from '@baseapp-frontend/design-system' -import { Box, Typography, useTheme } from '@mui/material' +import { Box, Typography } from '@mui/material' import Image from 'next/image' +import { useForm } from 'react-hook-form' import { Virtuoso } from 'react-virtuoso' -import useCurrentProfile from '../../profiles/context/useCurrentProfile' import { useAllProfilesList } from '../../profiles/graphql/queries/AllProfilesList' -import { useCreateChatRoomMutation } from '../graphql/mutations/CreateChatRoom' -import DefaultChatRoomListCard from './ChatRoomListCard' -import { - CreateChatRoomListContainer, - GroupChatContainer, - MainContainer, - SearchbarContainer, -} from './styled' -import { CreateChatRoomListProps } from './types' +import SearchNotFoundState from '../SearchNotFoundState' +import DefaultChatRoomListItem from './ChatRoomListItem' +import EmptyProfilesListState from './EmptyProfilesListState' +import { GroupChatContainer, MainContainer, SearchbarContainer } from './styled' +import { CreateChatRoomListProps, ProfileNode } from './types' const CreateChatRoomList: FC = ({ allProfilesRef, - ChatRoomListCard = DefaultChatRoomListCard, - ChatRoomListCardProps = {}, + ChatRoomListItem = DefaultChatRoomListItem, + ChatRoomListItemProps = {}, Searchbar = DefaultSearchbar, SearchbarProps = {}, VirtuosoProps = {}, @@ -40,20 +36,28 @@ const CreateChatRoomList: FC = ({ hasNext, refetch, } = useAllProfilesList(allProfilesRef) + const [isPending, startTransition] = useTransition() + const { control, reset, watch } = useForm({ defaultValues: { search: '' } }) - const currentProfile = useCurrentProfile() - - const theme = useTheme() + const handleSearchChange: ChangeEventHandler = (e) => { + const value = e.target.value || '' + startTransition(() => { + refetch({ q: value }) + }) + } - const [commit, isMutationInFlight] = useCreateChatRoomMutation() + const handleSearchClear = () => { + startTransition(() => { + reset() + refetch({ q: '' }) + }) + } - const memoizedItems = useMemo( + const profiles = useMemo( () => allProfiles?.edges.filter((edge: any) => edge?.node).map((edge: any) => edge?.node) || [], [allProfiles], ) - const [isPending, startTransition] = useTransition() - const renderLoadingState = () => { if (!isLoadingNext) return @@ -61,22 +65,45 @@ const CreateChatRoomList: FC = ({ ) } - const renderItem = (item: any) => { - if (!item) return null + const renderItem = (profile: ProfileNode) => { + if (!profile) return null return ( - + ) + } + + const renderListContent = () => { + const emptyProfilesList = profiles.length === 0 + const searchValue = watch('search') + + if (!isPending && searchValue && emptyProfilesList) return + + if (!isPending && emptyProfilesList) return + + return ( + renderItem(item)} + style={{ scrollbarWidth: 'none' }} + components={{ + Footer: renderLoadingState, + }} + endReached={() => { + if (hasNext) { + loadNext(5) + } + }} + {...VirtuosoProps} /> ) } @@ -84,11 +111,12 @@ const CreateChatRoomList: FC = ({ return ( - {/* @ts-ignore TODO: Check typing */} @@ -98,7 +126,7 @@ const CreateChatRoomList: FC = ({ width={48} height={48} sx={{ - bgcolor: theme.palette.primary.main, + bgcolor: 'primary.main', alignSelf: 'flex-start', justifySelf: 'center', }} @@ -114,23 +142,7 @@ const CreateChatRoomList: FC = ({ New Group - - renderItem(item)} - style={{ scrollbarWidth: 'none' }} - components={{ - Footer: renderLoadingState, - }} - endReached={() => { - if (hasNext) { - loadNext(5) - } - }} - {...VirtuosoProps} - /> - + {renderListContent()} ) } diff --git a/packages/components/modules/messages/CreateChatRoomList/styled.tsx b/packages/components/modules/messages/CreateChatRoomList/styled.tsx index 3b73df1a..2d8c725c 100644 --- a/packages/components/modules/messages/CreateChatRoomList/styled.tsx +++ b/packages/components/modules/messages/CreateChatRoomList/styled.tsx @@ -25,12 +25,3 @@ export const GroupChatContainer = styled(Box)(({ theme }) => ({ padding: `${theme.spacing(1.5)} ${theme.spacing(1.5)}`, }, })) - -export const CreateChatRoomListContainer = styled(Box)(({ theme }) => ({ - width: '100%', - height: '100%', - alignSelf: 'start', - [theme.breakpoints.down('sm')]: { - height: '100vh', - }, -})) diff --git a/packages/components/modules/messages/CreateChatRoomList/types.ts b/packages/components/modules/messages/CreateChatRoomList/types.ts index d56b005e..3ee2c930 100644 --- a/packages/components/modules/messages/CreateChatRoomList/types.ts +++ b/packages/components/modules/messages/CreateChatRoomList/types.ts @@ -4,15 +4,20 @@ import { SearchbarProps } from '@baseapp-frontend/design-system' import { VirtuosoProps } from 'react-virtuoso' +import { AllProfilesListFragment$data } from '../../../__generated__/AllProfilesListFragment.graphql' import { ChatRoomsQuery$data } from '../../../__generated__/ChatRoomsQuery.graphql' -import { ChatRoomListCardProps } from './ChatRoomListCard/types' +import { ChatRoomListItemProps } from './ChatRoomListItem/types' + +type AllProfiles = NonNullable +type AllProfilesEdges = AllProfiles['edges'] +export type ProfileNode = NonNullable['node'] export interface CreateChatRoomListProps extends PropsWithChildren { allProfilesRef: ChatRoomsQuery$data Searchbar?: FC SearchbarProps?: Partial - ChatRoomListCard?: FC - ChatRoomListCardProps?: Partial + ChatRoomListItem?: FC + ChatRoomListItemProps?: Partial VirtuosoProps?: Partial> setIsInExistingChatRoomsView: Dispatch> } diff --git a/packages/components/modules/messages/MessageItem/index.tsx b/packages/components/modules/messages/MessagesList/MessagesGroup/MessageItem/index.tsx similarity index 86% rename from packages/components/modules/messages/MessageItem/index.tsx rename to packages/components/modules/messages/MessagesList/MessagesGroup/MessageItem/index.tsx index c9a7f9af..bcd74799 100644 --- a/packages/components/modules/messages/MessageItem/index.tsx +++ b/packages/components/modules/messages/MessagesList/MessagesGroup/MessageItem/index.tsx @@ -3,8 +3,8 @@ import { FC } from 'react' import { Typography } from '@mui/material' import { useFragment } from 'react-relay' -import { useCurrentProfile } from '../../profiles' -import { MessageItemFragment } from '../graphql/queries/MessageItem' +import { useCurrentProfile } from '../../../../profiles' +import { MessageItemFragment } from '../../../graphql/queries/MessageItem' import { MessageItemContainer } from './styled' import { MessageItemProps } from './types' diff --git a/packages/components/modules/messages/MessageItem/styled.tsx b/packages/components/modules/messages/MessagesList/MessagesGroup/MessageItem/styled.tsx similarity index 100% rename from packages/components/modules/messages/MessageItem/styled.tsx rename to packages/components/modules/messages/MessagesList/MessagesGroup/MessageItem/styled.tsx diff --git a/packages/components/modules/messages/MessageItem/types.ts b/packages/components/modules/messages/MessagesList/MessagesGroup/MessageItem/types.ts similarity index 73% rename from packages/components/modules/messages/MessageItem/types.ts rename to packages/components/modules/messages/MessagesList/MessagesGroup/MessageItem/types.ts index 7bc2a492..3dee4d0f 100644 --- a/packages/components/modules/messages/MessageItem/types.ts +++ b/packages/components/modules/messages/MessagesList/MessagesGroup/MessageItem/types.ts @@ -1,6 +1,6 @@ import { BoxProps } from '@mui/material' -import { MessageItemFragment$key } from '../../../__generated__/MessageItemFragment.graphql' +import { MessageItemFragment$key } from '../../../../../__generated__/MessageItemFragment.graphql' export interface MessageItemProps { messageRef: MessageItemFragment$key diff --git a/packages/components/modules/messages/MessagesGroup/Timestamp/index.tsx b/packages/components/modules/messages/MessagesList/MessagesGroup/Timestamp/index.tsx similarity index 100% rename from packages/components/modules/messages/MessagesGroup/Timestamp/index.tsx rename to packages/components/modules/messages/MessagesList/MessagesGroup/Timestamp/index.tsx diff --git a/packages/components/modules/messages/MessagesGroup/Timestamp/types.ts b/packages/components/modules/messages/MessagesList/MessagesGroup/Timestamp/types.ts similarity index 100% rename from packages/components/modules/messages/MessagesGroup/Timestamp/types.ts rename to packages/components/modules/messages/MessagesList/MessagesGroup/Timestamp/types.ts diff --git a/packages/components/modules/messages/MessagesGroup/index.tsx b/packages/components/modules/messages/MessagesList/MessagesGroup/index.tsx similarity index 75% rename from packages/components/modules/messages/MessagesGroup/index.tsx rename to packages/components/modules/messages/MessagesList/MessagesGroup/index.tsx index 4e0ced21..c664948a 100644 --- a/packages/components/modules/messages/MessagesGroup/index.tsx +++ b/packages/components/modules/messages/MessagesList/MessagesGroup/index.tsx @@ -3,15 +3,15 @@ import { FC, useCallback, useMemo } from 'react' import { AvatarWithPlaceholder } from '@baseapp-frontend/design-system' import { datesDontHaveSameDay } from '@baseapp-frontend/utils' -import { Box, Typography } from '@mui/material' +import { Box, Divider, Typography, useTheme } from '@mui/material' import { DateTime } from 'luxon' -import { useCurrentProfile } from '../../profiles' -import DefaultMessageItem from '../MessageItem' +import { useCurrentProfile } from '../../../profiles' import { MAXIMUM_DIFF_TO_GROUP_MESSAGES_CREATED_TIME, MINIMUM_AMOUNT_OF_PARTICIPANTS_TO_SHOW_ROOM_TITLE, -} from '../constants' +} from '../../constants' +import DefaultMessageItem from './MessageItem' import Timestamp from './Timestamp' import { DateGroupTypography } from './styled' import { MessagesGroupProps } from './types' @@ -28,6 +28,7 @@ const MessagesGroup: FC = ({ MessageItemProps = {}, }) => { const { profile: currentProfile } = useCurrentProfile() + const theme = useTheme() const renderDateOnTopOfMessagesGroup = useCallback( (index: number) => { @@ -51,6 +52,38 @@ const MessagesGroup: FC = ({ [allMessages, allMessagesLastIndex, hasNext], ) + const renderUnreadMessagesDivider = useCallback( + (index: number) => { + const previousMessage = allMessages?.[index + 1] + const currentMessage = allMessages?.[index] + const hasPreviousMessage = !!previousMessage + const isFirstUnreadMessage = + currentMessage?.profile?.id !== currentProfile?.id && + !currentMessage?.isRead && + (!hasPreviousMessage || previousMessage?.isRead) + + if (!!currentMessage && isFirstUnreadMessage) { + return ( + + + New Messages + + + ) + } + + return null + }, + [allMessages, currentProfile, theme.palette.error.light], + ) + const renderLastMessageTime = useCallback( (index: number) => { const currentMessage = allMessages?.[index] @@ -100,11 +133,8 @@ const MessagesGroup: FC = ({ if (!message) return null return ( - + + {renderUnreadMessagesDivider(messageIndex)} {renderDateOnTopOfMessagesGroup(messageIndex)} {canShowAvatar && ( diff --git a/packages/components/modules/messages/MessagesGroup/styled.tsx b/packages/components/modules/messages/MessagesList/MessagesGroup/styled.tsx similarity index 100% rename from packages/components/modules/messages/MessagesGroup/styled.tsx rename to packages/components/modules/messages/MessagesList/MessagesGroup/styled.tsx diff --git a/packages/components/modules/messages/MessagesGroup/types.ts b/packages/components/modules/messages/MessagesList/MessagesGroup/types.ts similarity index 67% rename from packages/components/modules/messages/MessagesGroup/types.ts rename to packages/components/modules/messages/MessagesList/MessagesGroup/types.ts index 05a90d69..c35dba5e 100644 --- a/packages/components/modules/messages/MessagesGroup/types.ts +++ b/packages/components/modules/messages/MessagesList/MessagesGroup/types.ts @@ -1,8 +1,8 @@ import { FC } from 'react' -import { MessagesListFragment$data } from '../../../__generated__/MessagesListFragment.graphql' -import { MessageItemProps } from '../MessageItem/types' -import { MessageNode } from '../types' +import { MessagesListFragment$data } from '../../../../__generated__/MessagesListFragment.graphql' +import { MessageNode } from '../../types' +import { MessageItemProps } from './MessageItem/types' type Participants = NonNullable diff --git a/packages/components/modules/messages/MessagesGroup/utils.ts b/packages/components/modules/messages/MessagesList/MessagesGroup/utils.ts similarity index 100% rename from packages/components/modules/messages/MessagesGroup/utils.ts rename to packages/components/modules/messages/MessagesList/MessagesGroup/utils.ts diff --git a/packages/components/modules/messages/MessagesList/index.tsx b/packages/components/modules/messages/MessagesList/index.tsx index ebe2e056..e0dc1c4a 100644 --- a/packages/components/modules/messages/MessagesList/index.tsx +++ b/packages/components/modules/messages/MessagesList/index.tsx @@ -8,9 +8,11 @@ import { Virtuoso, VirtuosoHandle } from 'react-virtuoso' import { ChatRoomMessagesListPaginationQuery } from '../../../__generated__/ChatRoomMessagesListPaginationQuery.graphql' import { MessagesListFragment$key } from '../../../__generated__/MessagesListFragment.graphql' -import DefaultMessagesGroup from '../MessagesGroup' +import { useCurrentProfile } from '../../profiles' +import { useReadMessageMutation } from '../graphql/mutations/ReadMessages' import { MessagesListFragment } from '../graphql/queries/MessagesList' import useMessagesListSubscription from '../graphql/subscriptions/useMessagesListSubscription' +import DefaultMessagesGroup from './MessagesGroup' import { MESSAGES_TO_LOAD_NEXT } from './constants' import { MessagesListProps } from './types' @@ -29,6 +31,8 @@ const MessagesList: FC = ({ MessagesListFragment, roomRef, ) + const { profile } = useCurrentProfile() + const [commitMutation] = useReadMessageMutation() const totalNumberOfMessages = room?.allMessages?.totalCount ?? 0 const virtuosoRef = useRef(null) @@ -92,6 +96,7 @@ const MessagesList: FC = ({ = ({ loadNext(MESSAGES_TO_LOAD_NEXT) } }} + endReached={() => { + if (room?.unreadMessagesCount && room?.unreadMessagesCount > 0) { + commitMutation({ + variables: { + input: { + roomId: room.id, + profileId: profile?.id as string, + }, + }, + }) + } + }} components={{ Header: renderLoadingState, Footer: renderHeader, diff --git a/packages/components/modules/messages/MessagesList/types.ts b/packages/components/modules/messages/MessagesList/types.ts index c988fe31..032ccb8c 100644 --- a/packages/components/modules/messages/MessagesList/types.ts +++ b/packages/components/modules/messages/MessagesList/types.ts @@ -3,7 +3,7 @@ import { FC } from 'react' import { VirtuosoProps } from 'react-virtuoso' import { MessagesListFragment$key } from '../../../__generated__/MessagesListFragment.graphql' -import { MessagesGroupProps } from '../MessagesGroup/types' +import { MessagesGroupProps } from './MessagesGroup/types' export interface MessagesListProps { roomRef: MessagesListFragment$key diff --git a/packages/components/modules/messages/SearchNotFoundState/index.tsx b/packages/components/modules/messages/SearchNotFoundState/index.tsx new file mode 100644 index 00000000..974cb046 --- /dev/null +++ b/packages/components/modules/messages/SearchNotFoundState/index.tsx @@ -0,0 +1,19 @@ +import { SearchingImage } from '@baseapp-frontend/design-system' + +import { Box, Typography } from '@mui/material' + +const SearchNotFoundState = () => ( + + + + + No results found + + + Check your spelling or try another search. + + + +) + +export default SearchNotFoundState diff --git a/packages/components/modules/messages/context/ChatRoomProvider/index.tsx b/packages/components/modules/messages/context/ChatRoomProvider/index.tsx index cffd3924..f2d2bedf 100644 --- a/packages/components/modules/messages/context/ChatRoomProvider/index.tsx +++ b/packages/components/modules/messages/context/ChatRoomProvider/index.tsx @@ -1,3 +1,5 @@ +'use client' + import { FC, PropsWithChildren, createContext, useRef } from 'react' import { StoreApi, create } from 'zustand' diff --git a/packages/components/modules/messages/graphql/mutations/ReadMessages.ts b/packages/components/modules/messages/graphql/mutations/ReadMessages.ts new file mode 100644 index 00000000..483d6dfa --- /dev/null +++ b/packages/components/modules/messages/graphql/mutations/ReadMessages.ts @@ -0,0 +1,48 @@ +import { useNotification } from '@baseapp-frontend/utils' + +import { Disposable, UseMutationConfig, graphql, useMutation } from 'react-relay' + +import { ReadMessagesMutation } from '../../../../__generated__/ReadMessagesMutation.graphql' + +export const ReadMessagesMutationQuery = graphql` + mutation ReadMessagesMutation($input: ChatRoomReadMessagesInput!) { + chatRoomReadMessages(input: $input) { + room { + id + unreadMessagesCount + ...RoomFragment + } + errors { + field + messages + } + } + } +` + +export const useReadMessageMutation = (): [ + (config: UseMutationConfig) => Disposable, + boolean, +] => { + const { sendToast } = useNotification() + const [commitMutation, isMutationInFlight] = + useMutation(ReadMessagesMutationQuery) + + const commit = (config: UseMutationConfig) => + commitMutation({ + ...config, + onCompleted: (response, errors) => { + errors?.forEach((error) => { + sendToast(error.message, { type: 'error' }) + }) + + config?.onCompleted?.(response, errors) + }, + onError: (error) => { + sendToast(error.message, { type: 'error' }) + config?.onError?.(error) + }, + }) + + return [commit, isMutationInFlight] +} diff --git a/packages/components/modules/messages/graphql/queries/ChatRoomQuery.ts b/packages/components/modules/messages/graphql/queries/ChatRoomQuery.ts index 3de0c53a..6051a161 100644 --- a/packages/components/modules/messages/graphql/queries/ChatRoomQuery.ts +++ b/packages/components/modules/messages/graphql/queries/ChatRoomQuery.ts @@ -19,6 +19,7 @@ export const ChatRoomQuery = graphql` } } } + unreadMessagesCount ...MessagesListFragment } } diff --git a/packages/components/modules/messages/graphql/queries/MessageItem.ts b/packages/components/modules/messages/graphql/queries/MessageItem.ts index a940a9c2..0ac7bde9 100644 --- a/packages/components/modules/messages/graphql/queries/MessageItem.ts +++ b/packages/components/modules/messages/graphql/queries/MessageItem.ts @@ -9,6 +9,7 @@ export const MessageItemFragment = graphql` inReplyTo { id } + isRead pk profile { id diff --git a/packages/components/modules/messages/graphql/queries/MessagesList.ts b/packages/components/modules/messages/graphql/queries/MessagesList.ts index 63ef3525..00202050 100644 --- a/packages/components/modules/messages/graphql/queries/MessagesList.ts +++ b/packages/components/modules/messages/graphql/queries/MessagesList.ts @@ -8,6 +8,7 @@ export const MessagesListFragment = graphql` participants { totalCount } + unreadMessagesCount allMessages(first: $count, after: $cursor) @connection(key: "chatRoom_allMessages") { totalCount edges { @@ -21,6 +22,7 @@ export const MessagesListFragment = graphql` url } } + isRead ...MessageItemFragment } } diff --git a/packages/components/modules/messages/graphql/queries/RoomsList.ts b/packages/components/modules/messages/graphql/queries/RoomsList.ts index 655fe73a..797276f7 100644 --- a/packages/components/modules/messages/graphql/queries/RoomsList.ts +++ b/packages/components/modules/messages/graphql/queries/RoomsList.ts @@ -9,10 +9,13 @@ export const RoomsListFragment = graphql` cursor: { type: "String" } count: { type: "Int", defaultValue: 5 } q: { type: "String", defaultValue: null } + unreadMessages: { type: "Boolean", defaultValue: false } ) @refetchable(queryName: "chatRoomsPaginationQuery") { id - chatRooms(first: $count, after: $cursor, q: $q) @connection(key: "roomsList_chatRooms") { + unreadMessagesCount + chatRooms(first: $count, after: $cursor, q: $q, unreadMessages: $unreadMessages) + @connection(key: "roomsList_chatRooms") { edges { node { id @@ -25,7 +28,6 @@ export const RoomsListFragment = graphql` endCursor } } - unreadMessagesCount } ` diff --git a/packages/components/modules/messages/graphql/subscriptions/useMessageCountUpdateSubscription.tsx b/packages/components/modules/messages/graphql/subscriptions/useMessageCountUpdateSubscription.tsx new file mode 100644 index 00000000..e2659f46 --- /dev/null +++ b/packages/components/modules/messages/graphql/subscriptions/useMessageCountUpdateSubscription.tsx @@ -0,0 +1,46 @@ +import { useMemo } from 'react' + +import { graphql, useSubscription } from 'react-relay' + +import { useCurrentProfile } from '../../../profiles' + +const MessageCountUpdateSubscription = graphql` + subscription useMessageCountUpdateSubscription($profileId: ID!) { + chatRoomOnMessagesCountUpdate(profileId: $profileId) { + profile { + id + unreadMessagesCount + chatRooms { + totalCount + edges { + node { + id + __typename + unreadMessagesCount + ...RoomFragment + } + } + } + } + } + } +` + +const useMessageCountUpdate = () => { + const { profile } = useCurrentProfile() + + const config = useMemo( + () => ({ + subscription: MessageCountUpdateSubscription, + onError: console.error, + variables: { + profileId: profile?.id, + }, + }), + [profile?.id], + ) + + return useSubscription(config) +} + +export default useMessageCountUpdate diff --git a/packages/components/modules/messages/graphql/subscriptions/useRoomListSubscription.tsx b/packages/components/modules/messages/graphql/subscriptions/useRoomListSubscription.tsx index 8df8f10b..d1e78990 100644 --- a/packages/components/modules/messages/graphql/subscriptions/useRoomListSubscription.tsx +++ b/packages/components/modules/messages/graphql/subscriptions/useRoomListSubscription.tsx @@ -3,6 +3,8 @@ import { useMemo } from 'react' import { ConnectionHandler, graphql, useSubscription } from 'react-relay' import { RecordSourceSelectorProxy } from 'relay-runtime' +import { useCurrentProfile } from '../../../profiles' + const RoomListSubscription = graphql` subscription useRoomListSubscription($profileId: ID!) { chatRoomOnRoomUpdate(profileId: $profileId) { @@ -32,13 +34,14 @@ const RoomListSubscription = graphql` ` // TODO: check if BE subscription is working properly -const useRoomListSubscription = (nodeId: string, currentProfileId: string) => { +const useRoomListSubscription = (nodeId: string) => { + const { profile } = useCurrentProfile() const config = useMemo( () => ({ subscription: RoomListSubscription, onError: console.error, variables: { - profileId: currentProfileId, // TODO: use currentProfile hook when available + profileId: profile?.id, }, updater: (store: RecordSourceSelectorProxy, data: any) => { const node = store.get(nodeId) diff --git a/packages/components/modules/messages/index.ts b/packages/components/modules/messages/index.ts index bcd215c9..50a8d1df 100644 --- a/packages/components/modules/messages/index.ts +++ b/packages/components/modules/messages/index.ts @@ -1,6 +1,3 @@ -export { default as MessageItem } from './MessageItem' -export type * from './MessageItem/types' - export { default as MessagesList } from './MessagesList' export type * from './MessagesList/types' @@ -15,10 +12,12 @@ export type * from './SendMessage/types' export { default as CreateChatRoomList } from './CreateChatRoomList' export type * from './CreateChatRoomList/types' + export * from './context' export * from './graphql/mutations/SendMessage' export * from './graphql/mutations/CreateChatRoom' +export * from './graphql/mutations/ReadMessages' export * from './graphql/queries/MessageItem' export * from './graphql/queries/MessagesList' @@ -27,3 +26,4 @@ export * from './graphql/queries/Room' export * from './graphql/queries/RoomsList' export { default as useMessagesListSubscription } from './graphql/subscriptions/useMessagesListSubscription' +export { default as useMessageCountUpdateSubscription } from './graphql/subscriptions/useMessageCountUpdateSubscription' diff --git a/packages/components/modules/navigations/Header/AccountMenu/AccountPopover/LogoutItem/index.tsx b/packages/components/modules/navigations/Header/AccountMenu/AccountPopover/LogoutItem/index.tsx index bda65e30..3afe0cc0 100644 --- a/packages/components/modules/navigations/Header/AccountMenu/AccountPopover/LogoutItem/index.tsx +++ b/packages/components/modules/navigations/Header/AccountMenu/AccountPopover/LogoutItem/index.tsx @@ -9,7 +9,7 @@ import { LogoutItemProps } from './types' const LogoutItem: FC = ({ children, handlePopoverOnClose, - logoutButtonLabel = 'logout', + logoutButtonLabel = 'Logout', }) => { const { logout } = useLogout() diff --git a/packages/components/modules/navigations/Header/styled.tsx b/packages/components/modules/navigations/Header/styled.tsx index cea7794d..b7b00200 100644 --- a/packages/components/modules/navigations/Header/styled.tsx +++ b/packages/components/modules/navigations/Header/styled.tsx @@ -3,7 +3,7 @@ import { bgBlur } from '@baseapp-frontend/design-system' import { AppBar } from '@mui/material' import { styled } from '@mui/material/styles' -import { HEADER, NAV } from '../constants' +import { HEADER_HEIGHT, NAV_WIDTH } from '../constants' import { CustomAppBarProps } from './types' export const CustomAppBar = styled(AppBar)(({ theme, themeLayout }) => { @@ -13,7 +13,7 @@ export const CustomAppBar = styled(AppBar)(({ theme, themeLay const isNavMini = themeLayout === 'mini' return { - height: HEADER.H_MOBILE, + height: HEADER_HEIGHT.MOBILE, zIndex: theme.zIndex.appBar + 1, ...bgBlur({ color: theme.palette.background.default, @@ -24,17 +24,17 @@ export const CustomAppBar = styled(AppBar)(({ theme, themeLay width: '100%', [theme.breakpoints.up('lg')]: { ...(isNavVertical && { - width: `calc(100% - ${NAV.W_VERTICAL + 1}px)`, - height: HEADER.H_DESKTOP, + width: `calc(100% - ${NAV_WIDTH.VERTICAL + 1}px)`, + height: HEADER_HEIGHT.DESKTOP, }), ...((isNavHorizontal || isNavCentered) && { width: '100%', backgroundColor: theme.palette.background.default, - height: HEADER.H_DESKTOP_OFFSET, + height: HEADER_HEIGHT.DESKTOP_OFFSET, borderBottom: `dashed 1px ${theme.palette.divider}`, }), ...(isNavMini && { - width: `calc(100% - ${NAV.W_MINI + 1}px)`, + width: `calc(100% - ${NAV_WIDTH.MINI + 1}px)`, }), }, } diff --git a/packages/components/modules/navigations/NavHorizontal/index.tsx b/packages/components/modules/navigations/NavHorizontal/index.tsx index 4ae9554d..8a8181c4 100644 --- a/packages/components/modules/navigations/NavHorizontal/index.tsx +++ b/packages/components/modules/navigations/NavHorizontal/index.tsx @@ -8,7 +8,7 @@ import AppBar from '@mui/material/AppBar' import Toolbar from '@mui/material/Toolbar' import { useTheme } from '@mui/material/styles' -import { HEADER } from '../constants' +import { HEADER_HEIGHT } from '../constants' import NavSectionHorizontal from '../shared/NavSectionHorizontal' import VerticalDrawer from '../shared/VerticalDrawer' import HeaderShadow from './HeaderShadow' @@ -26,7 +26,7 @@ const NavHorizontal: FC = ({ navData, openNav, onCloseNav }) diff --git a/packages/components/modules/navigations/NavMini/index.tsx b/packages/components/modules/navigations/NavMini/index.tsx index f99979ab..fdb928a6 100644 --- a/packages/components/modules/navigations/NavMini/index.tsx +++ b/packages/components/modules/navigations/NavMini/index.tsx @@ -7,7 +7,7 @@ import { Logo, hideScroll, useResponsive } from '@baseapp-frontend/design-system import Box from '@mui/material/Box' import Stack from '@mui/material/Stack' -import { NAV } from '../constants' +import { NAV_WIDTH } from '../constants' import NavToggleButton from '../shared/NavToggleButton' import VerticalDrawer from '../shared/VerticalDrawer' import NavSectionMini from './NavSectionMini' @@ -32,7 +32,7 @@ const NavMini: FC = ({ @@ -42,7 +42,7 @@ const NavMini: FC = ({ setSettings={setSettings} sx={{ top: 22, - left: NAV.W_MINI - 12, + left: NAV_WIDTH.MINI - 12, }} /> )} @@ -51,7 +51,7 @@ const NavMini: FC = ({ pb: 2, height: 1, position: 'fixed', - width: NAV.W_MINI, + width: NAV_WIDTH.MINI, borderRight: (theme) => `solid 1px ${theme.palette.divider}`, ...hideScroll.x, }} diff --git a/packages/components/modules/navigations/NavVertical/index.tsx b/packages/components/modules/navigations/NavVertical/index.tsx index bc21145b..a8237f85 100644 --- a/packages/components/modules/navigations/NavVertical/index.tsx +++ b/packages/components/modules/navigations/NavVertical/index.tsx @@ -7,7 +7,7 @@ import { Logo, Scrollbar, useResponsive } from '@baseapp-frontend/design-system' import Box from '@mui/material/Box' import Stack from '@mui/material/Stack' -import { NAV } from '../constants' +import { NAV_WIDTH } from '../constants' import NavSectionVertical from '../shared/NavSectionVertical' import NavToggleButton from '../shared/NavToggleButton' import VerticalDrawer from '../shared/VerticalDrawer' @@ -32,7 +32,7 @@ const NavVertical: FC = ({ @@ -41,7 +41,7 @@ const NavVertical: FC = ({ sx={{ height: 1, position: 'fixed', - width: NAV.W_VERTICAL, + width: NAV_WIDTH.VERTICAL, borderRight: (theme) => `solid 1px ${theme.palette.divider}`, }} > diff --git a/packages/components/modules/navigations/NavigationLayout/MainContainer/styled.tsx b/packages/components/modules/navigations/NavigationLayout/MainContainer/styled.tsx index 6fe4d1c9..c6c66681 100644 --- a/packages/components/modules/navigations/NavigationLayout/MainContainer/styled.tsx +++ b/packages/components/modules/navigations/NavigationLayout/MainContainer/styled.tsx @@ -1,7 +1,7 @@ import { Box, BoxProps } from '@mui/material' import { styled } from '@mui/material/styles' -import { HEADER, NAV } from '../../constants' +import { NAV_PADDING_DOWN_TO_LG, NAV_PADDING_UP_TO_LG, NAV_WIDTH } from '../../constants' import { NavVerticalContainerProps } from './types' export const CommonContainer = styled(Box)(({ theme }) => ({ @@ -18,18 +18,26 @@ export const NavHorizontalContainer = styled(CommonContainer)(({ theme }) => ({ display: 'flex', flexDirection: 'column', minHeight: 1, - paddingBottom: 10, - paddingTop: `${HEADER.H_MOBILE + 24}px`, + paddingBottom: NAV_PADDING_DOWN_TO_LG.horizontal.bottom, + paddingTop: NAV_PADDING_DOWN_TO_LG.horizontal.top, [theme.breakpoints.up('lg')]: { - paddingTop: `${HEADER.H_MOBILE * 2 + 40}px`, - paddingBottom: 15, + paddingTop: NAV_PADDING_DOWN_TO_LG.horizontal.top, + paddingBottom: NAV_PADDING_UP_TO_LG.horizontal.bottom, + }, + [theme.breakpoints.down('sm')]: { + paddingBottom: 0, }, })) export const NavCenteredContainer = styled(NavHorizontalContainer)(({ theme }) => ({ - paddingTop: `${HEADER.H_MOBILE + 32}px`, + paddingTop: NAV_PADDING_DOWN_TO_LG.centered.top, + paddingBottom: NAV_PADDING_DOWN_TO_LG.centered.bottom, [theme.breakpoints.up('lg')]: { - paddingTop: `${HEADER.H_MOBILE + 24}px`, + paddingTop: NAV_PADDING_UP_TO_LG.centered.top, + paddingBottom: NAV_PADDING_UP_TO_LG.centered.bottom, + }, + [theme.breakpoints.down('sm')]: { + paddingBottom: 0, }, })) @@ -39,10 +47,21 @@ export const NavVerticalContainer = styled(CommonContainer) = ({ + children, + themeLayout, + ...props +}) => { + if (themeLayout === 'horizontal') { + return {children} + } + + if (themeLayout === 'centered') { + return {children} + } + + return {children} +} + +export default ViewportHeightContainer diff --git a/packages/components/modules/navigations/ViewportHeightContainer/styled.tsx b/packages/components/modules/navigations/ViewportHeightContainer/styled.tsx new file mode 100644 index 00000000..40ffabcf --- /dev/null +++ b/packages/components/modules/navigations/ViewportHeightContainer/styled.tsx @@ -0,0 +1,34 @@ +import { Box } from '@mui/material' +import { styled } from '@mui/material/styles' + +import { NAV_PADDING_DOWN_TO_LG, NAV_PADDING_UP_TO_LG } from '../constants' + +export const HorizontalContainer = styled(Box)(({ theme }) => ({ + height: `calc(100vh - ${NAV_PADDING_DOWN_TO_LG.horizontal.top + NAV_PADDING_DOWN_TO_LG.horizontal.bottom}px)`, + [theme.breakpoints.up('lg')]: { + height: `calc(100vh - ${NAV_PADDING_UP_TO_LG.horizontal.top + NAV_PADDING_UP_TO_LG.horizontal.bottom}px)`, + }, + [theme.breakpoints.down('sm')]: { + height: `calc(100vh - ${NAV_PADDING_DOWN_TO_LG.horizontal.top}px)`, + }, +})) + +export const CenteredContainer = styled(Box)(({ theme }) => ({ + height: `calc(100vh - ${NAV_PADDING_DOWN_TO_LG.centered.top + NAV_PADDING_DOWN_TO_LG.centered.bottom}px)`, + [theme.breakpoints.up('lg')]: { + height: `calc(100vh - ${NAV_PADDING_UP_TO_LG.centered.top + NAV_PADDING_UP_TO_LG.centered.bottom}px)`, + }, + [theme.breakpoints.down('sm')]: { + height: `calc(100vh - ${NAV_PADDING_DOWN_TO_LG.centered.top}px)`, + }, +})) + +export const VerticalContainer = styled(Box)(({ theme }) => ({ + height: `calc(100vh - ${NAV_PADDING_DOWN_TO_LG.vertical.top + NAV_PADDING_DOWN_TO_LG.vertical.bottom}px)`, + [theme.breakpoints.up('lg')]: { + height: `calc(100vh - ${NAV_PADDING_UP_TO_LG.vertical.top + NAV_PADDING_UP_TO_LG.vertical.bottom}px)`, + }, + [theme.breakpoints.down('sm')]: { + height: `calc(100vh - ${NAV_PADDING_DOWN_TO_LG.vertical.top}px)`, + }, +})) diff --git a/packages/components/modules/navigations/ViewportHeightContainer/types.ts b/packages/components/modules/navigations/ViewportHeightContainer/types.ts new file mode 100644 index 00000000..e68f0eac --- /dev/null +++ b/packages/components/modules/navigations/ViewportHeightContainer/types.ts @@ -0,0 +1,9 @@ +import { PropsWithChildren } from 'react' + +import { ThemeLayout } from '@baseapp-frontend/design-system' + +import type { BoxProps } from '@mui/material' + +export interface ViewportHeightContainerProps extends PropsWithChildren, BoxProps { + themeLayout: ThemeLayout +} diff --git a/packages/components/modules/navigations/constants.ts b/packages/components/modules/navigations/constants.ts index 866fae85..ec0ce3fe 100644 --- a/packages/components/modules/navigations/constants.ts +++ b/packages/components/modules/navigations/constants.ts @@ -1,10 +1,40 @@ -export const HEADER = { - H_MOBILE: 64, - H_DESKTOP: 80, - H_DESKTOP_OFFSET: 80 - 16, +export const HEADER_HEIGHT = { + MOBILE: 64, + DESKTOP: 80, + DESKTOP_OFFSET: 80 - 16, } -export const NAV = { - W_VERTICAL: 280, - W_MINI: 88, +export const NAV_WIDTH = { + VERTICAL: 280, + MINI: 88, +} + +export const NAV_PADDING_UP_TO_LG = { + horizontal: { + top: HEADER_HEIGHT.MOBILE * 2 + 40, + bottom: 15, + }, + centered: { + top: HEADER_HEIGHT.MOBILE + 24, + bottom: 0, + }, + vertical: { + top: HEADER_HEIGHT.DESKTOP + 8, + bottom: HEADER_HEIGHT.DESKTOP + 8, + }, +} + +export const NAV_PADDING_DOWN_TO_LG = { + horizontal: { + top: HEADER_HEIGHT.MOBILE + 24, + bottom: 10, + }, + centered: { + top: HEADER_HEIGHT.MOBILE + 32, + bottom: 0, + }, + vertical: { + top: HEADER_HEIGHT.MOBILE + 8, + bottom: HEADER_HEIGHT.MOBILE + 8, + }, } diff --git a/packages/components/modules/navigations/index.ts b/packages/components/modules/navigations/index.ts index 34ae5781..787412b6 100644 --- a/packages/components/modules/navigations/index.ts +++ b/packages/components/modules/navigations/index.ts @@ -22,4 +22,8 @@ export type * from './Header/AccountMenu/types' export { default as AccountPopover } from './Header/AccountMenu/AccountPopover' export type * from './Header/AccountMenu/AccountPopover/types' +export { default as ViewportHeightContainer } from './ViewportHeightContainer' +export type * from './ViewportHeightContainer/types' + +export * from './constants' export type * from './types' diff --git a/packages/components/modules/navigations/shared/NavToggleButton/index.tsx b/packages/components/modules/navigations/shared/NavToggleButton/index.tsx index c1e2de68..f405699c 100644 --- a/packages/components/modules/navigations/shared/NavToggleButton/index.tsx +++ b/packages/components/modules/navigations/shared/NavToggleButton/index.tsx @@ -3,7 +3,7 @@ import { ChevronIcon, bgBlur } from '@baseapp-frontend/design-system' import IconButton from '@mui/material/IconButton' import { useTheme } from '@mui/material/styles' -import { NAV } from '../../constants' +import { NAV_WIDTH } from '../../constants' import { NavToggleButtonProps } from './types' export default function NavToggleButton({ @@ -24,7 +24,7 @@ export default function NavToggleButton({ p: 0.5, top: 32, position: 'fixed', - left: NAV.W_VERTICAL - 12, + left: NAV_WIDTH.VERTICAL - 12, zIndex: theme.zIndex.appBar + 1, border: `solid 1px ${theme.palette.divider}`, ...bgBlur({ opacity: 0.48, color: theme.palette.background.default }), diff --git a/packages/components/modules/navigations/shared/VerticalDrawer/index.tsx b/packages/components/modules/navigations/shared/VerticalDrawer/index.tsx index fa141e4b..1f1ebccd 100644 --- a/packages/components/modules/navigations/shared/VerticalDrawer/index.tsx +++ b/packages/components/modules/navigations/shared/VerticalDrawer/index.tsx @@ -8,7 +8,7 @@ import Box from '@mui/material/Box' import Drawer from '@mui/material/Drawer' import { usePathname } from 'next/navigation' -import { NAV } from '../../constants' +import { NAV_WIDTH } from '../../constants' import NavSectionVertical from '../NavSectionVertical' import { VerticalDrawerProps } from './types' @@ -27,7 +27,7 @@ const VerticalDrawer: FC = ({ navData, LogoIcon, openNav, o onClose={onCloseNav} PaperProps={{ sx: { - width: NAV.W_VERTICAL, + width: NAV_WIDTH.VERTICAL, }, }} > diff --git a/packages/components/modules/profiles/ProfilePopover/ProfilesList/ProfileMenuItem/index.tsx b/packages/components/modules/profiles/ProfilePopover/ProfilesList/ProfileMenuItem/index.tsx index 696ce953..1e47f5e1 100644 --- a/packages/components/modules/profiles/ProfilePopover/ProfilesList/ProfileMenuItem/index.tsx +++ b/packages/components/modules/profiles/ProfilePopover/ProfilesList/ProfileMenuItem/index.tsx @@ -5,8 +5,8 @@ import { AvatarWithPlaceholder, CheckMarkIcon } from '@baseapp-frontend/design-s import { Box, Typography } from '@mui/material' import { readInlineData } from 'react-relay' -import { ProfileItemFragment$key } from '../../../../../__generated__/ProfileItemFragment.graphql' -import { ProfileItemFragment } from '../../../graphql/queries/ProfileItem' +import { ProfileItemInlineFragment$key } from '../../../../../__generated__/ProfileItemInlineFragment.graphql' +import { ProfileItemInlineFragment } from '../../../graphql/queries/ProfileItemInline' import { StyledMenuItem } from './styled' import { ProfileMenuItemProps } from './types' @@ -18,7 +18,10 @@ const ProfileMenuItem: FC = ({ width = 36, height = 36, }) => { - const profile = readInlineData(ProfileItemFragment, profileRef) + const profile = readInlineData( + ProfileItemInlineFragment, + profileRef, + ) const profileUrlPath = profile.urlPath?.path const isActiveProfile = profile.id === currentProfile?.id diff --git a/packages/components/modules/profiles/ProfilePopover/ProfilesList/ProfileMenuItem/types.ts b/packages/components/modules/profiles/ProfilePopover/ProfilesList/ProfileMenuItem/types.ts index 1b595028..62df6d1c 100644 --- a/packages/components/modules/profiles/ProfilePopover/ProfilesList/ProfileMenuItem/types.ts +++ b/packages/components/modules/profiles/ProfilePopover/ProfilesList/ProfileMenuItem/types.ts @@ -1,16 +1,16 @@ import type { AvatarWithPlaceholderProps } from '@baseapp-frontend/design-system' -import { MenuItemProps } from '@mui/material' +import { type MenuItemProps } from '@mui/material' import type { - ProfileItemFragment$data, - ProfileItemFragment$key, -} from '../../../../../__generated__/ProfileItemFragment.graphql' + ProfileItemInlineFragment$data, + ProfileItemInlineFragment$key, +} from '../../../../../__generated__/ProfileItemInlineFragment.graphql' export interface ProfileMenuItemProps { - profileRef: ProfileItemFragment$key - onProfileChange: (newProfile: ProfileItemFragment$data) => void - currentProfile?: ProfileItemFragment$data + profileRef: ProfileItemInlineFragment$key + onProfileChange: (newProfile: ProfileItemInlineFragment$data) => void + currentProfile?: ProfileItemInlineFragment$data avatarProps?: AvatarWithPlaceholderProps width?: number height?: number diff --git a/packages/components/modules/profiles/ProfilePopover/ProfilesList/index.tsx b/packages/components/modules/profiles/ProfilePopover/ProfilesList/index.tsx index 4e45abe2..c53c014d 100644 --- a/packages/components/modules/profiles/ProfilePopover/ProfilesList/index.tsx +++ b/packages/components/modules/profiles/ProfilePopover/ProfilesList/index.tsx @@ -8,7 +8,7 @@ import { useNotification } from '@baseapp-frontend/utils' import { Box, ButtonBase, Divider, Slide } from '@mui/material' import { useLazyLoadQuery } from 'react-relay' -import { ProfileItemFragment$data } from '../../../../__generated__/ProfileItemFragment.graphql' +import { ProfileItemInlineFragment$data } from '../../../../__generated__/ProfileItemInlineFragment.graphql' import { ProfilesListQuery as ProfilesListQueryType } from '../../../../__generated__/ProfilesListQuery.graphql' import useCurrentProfile from '../../context/useCurrentProfile' import { ProfilesListQuery } from '../../graphql/queries/ProfilesList' @@ -22,7 +22,7 @@ const ProfilesList: FC = ({ handleCloseSubmenu, MenuItemProps const { sendToast } = useNotification() const { profile: currentProfile, setCurrentProfile } = useCurrentProfile() - const handleProfileChange = (profile: ProfileItemFragment$data) => { + const handleProfileChange = (profile: ProfileItemInlineFragment$data) => { if (currentProfile?.id !== profile.id) { setCurrentProfile({ profile }) sendToast(`Switched to ${profile.name}`) diff --git a/packages/components/modules/profiles/context/CurrentProfileProvider/__tests__/CurrentProfileProvider.test.tsx b/packages/components/modules/profiles/context/CurrentProfileProvider/__tests__/CurrentProfileProvider.test.tsx index 68d779e8..033ea59b 100644 --- a/packages/components/modules/profiles/context/CurrentProfileProvider/__tests__/CurrentProfileProvider.test.tsx +++ b/packages/components/modules/profiles/context/CurrentProfileProvider/__tests__/CurrentProfileProvider.test.tsx @@ -2,7 +2,7 @@ import { createTestEnvironment } from '@baseapp-frontend/graphql' import { act, render, waitFor } from '@baseapp-frontend/test' import { LOGOUT_EVENT, eventEmitter } from '@baseapp-frontend/utils' -import { ProfileItemFragment$data } from '../../../../../__generated__/ProfileItemFragment.graphql' +import { ProfileItemInlineFragment$data } from '../../../../../__generated__/ProfileItemInlineFragment.graphql' import { CURRENT_PROFILE_STORAGE_KEY } from '../constants' import { CurrentProfileState } from '../types' import { mockUserProfileFactory } from './__mock__/profiles' @@ -27,7 +27,7 @@ describe('CurrentProfileProvider', () => { const loadPreStoredData = (customUserMockData: any, customUserProfileMockData: any) => { const storedCurrentProfile: CurrentProfileState = { - profile: customUserProfileMockData.data.me.profile as ProfileItemFragment$data, + profile: customUserProfileMockData.data.me.profile as ProfileItemInlineFragment$data, userId: customUserMockData.id, } diff --git a/packages/components/modules/profiles/context/CurrentProfileProvider/index.tsx b/packages/components/modules/profiles/context/CurrentProfileProvider/index.tsx index 933153b6..f236bae1 100644 --- a/packages/components/modules/profiles/context/CurrentProfileProvider/index.tsx +++ b/packages/components/modules/profiles/context/CurrentProfileProvider/index.tsx @@ -9,9 +9,9 @@ import { Environment, fetchQuery, readInlineData, useRelayEnvironment } from 're import { StoreApi, create } from 'zustand' import { persist } from 'zustand/middleware' -import { ProfileItemFragment$key } from '../../../../__generated__/ProfileItemFragment.graphql' +import { ProfileItemInlineFragment$key } from '../../../../__generated__/ProfileItemInlineFragment.graphql' import { UserProfileQuery as UserProfileQueryType } from '../../../../__generated__/UserProfileQuery.graphql' -import { ProfileItemFragment } from '../../graphql/queries/ProfileItem' +import { ProfileItemInlineFragment } from '../../graphql/queries/ProfileItemInline' import { UserProfileQuery } from '../../graphql/queries/UserProfile' import { CURRENT_PROFILE_STORAGE_KEY, INITIAL_CURRENT_PROFILE_STATE } from './constants' import { UseCurrentProfile } from './types' @@ -27,7 +27,7 @@ const fetchUserProfile = async (environment: Environment) => { ).toPromise() const userProfile = data?.me?.profile - ? readInlineData(ProfileItemFragment, data.me.profile) + ? readInlineData(ProfileItemInlineFragment, data.me.profile) : null return userProfile diff --git a/packages/components/modules/profiles/context/CurrentProfileProvider/types.ts b/packages/components/modules/profiles/context/CurrentProfileProvider/types.ts index 4ff5e0b3..888edb74 100644 --- a/packages/components/modules/profiles/context/CurrentProfileProvider/types.ts +++ b/packages/components/modules/profiles/context/CurrentProfileProvider/types.ts @@ -1,7 +1,7 @@ -import { ProfileItemFragment$data } from '../../../../__generated__/ProfileItemFragment.graphql' +import { ProfileItemInlineFragment$data } from '../../../../__generated__/ProfileItemInlineFragment.graphql' export type CurrentProfileState = { - profile?: ProfileItemFragment$data + profile?: ProfileItemInlineFragment$data userId?: number } diff --git a/packages/components/modules/profiles/graphql/queries/AllProfilesList.ts b/packages/components/modules/profiles/graphql/queries/AllProfilesList.ts index 6283730b..9142aa43 100644 --- a/packages/components/modules/profiles/graphql/queries/AllProfilesList.ts +++ b/packages/components/modules/profiles/graphql/queries/AllProfilesList.ts @@ -21,14 +21,7 @@ export const fragmentQuery = graphql` edges { node { id - pk - name - image(width: 48, height: 48) { - url - } - urlPath { - path - } + ...ProfileItemFragment } } } diff --git a/packages/components/modules/profiles/graphql/queries/ProfileItem.ts b/packages/components/modules/profiles/graphql/queries/ProfileItem.ts index 74c2638a..5ba5b2e4 100644 --- a/packages/components/modules/profiles/graphql/queries/ProfileItem.ts +++ b/packages/components/modules/profiles/graphql/queries/ProfileItem.ts @@ -2,7 +2,6 @@ import { graphql } from 'react-relay' export const ProfileItemFragment = graphql` fragment ProfileItemFragment on Profile - @inline @argumentDefinitions(avatarSize: { type: "Int", defaultValue: 100 }) { id name diff --git a/packages/components/modules/profiles/graphql/queries/ProfileItemInline.ts b/packages/components/modules/profiles/graphql/queries/ProfileItemInline.ts new file mode 100644 index 00000000..f54934ba --- /dev/null +++ b/packages/components/modules/profiles/graphql/queries/ProfileItemInline.ts @@ -0,0 +1,17 @@ +import { graphql } from 'react-relay' + +// TODO: remove this +export const ProfileItemInlineFragment = graphql` + fragment ProfileItemInlineFragment on Profile + @inline + @argumentDefinitions(avatarSize: { type: "Int", defaultValue: 100 }) { + id + name + image(width: $avatarSize, height: $avatarSize) { + url + } + urlPath { + path + } + } +` diff --git a/packages/components/modules/profiles/graphql/queries/ProfilesList.ts b/packages/components/modules/profiles/graphql/queries/ProfilesList.ts index 23a9e46d..71537bba 100644 --- a/packages/components/modules/profiles/graphql/queries/ProfilesList.ts +++ b/packages/components/modules/profiles/graphql/queries/ProfilesList.ts @@ -1,10 +1,11 @@ import { graphql } from 'react-relay' +// TODO: remove inline fragment export const ProfilesListQuery = graphql` query ProfilesListQuery { me { profiles { - ...ProfileItemFragment + ...ProfileItemInlineFragment } } } diff --git a/packages/components/modules/profiles/graphql/queries/UserProfile.ts b/packages/components/modules/profiles/graphql/queries/UserProfile.ts index 6057b852..8e18e539 100644 --- a/packages/components/modules/profiles/graphql/queries/UserProfile.ts +++ b/packages/components/modules/profiles/graphql/queries/UserProfile.ts @@ -1,10 +1,11 @@ import { graphql } from 'react-relay' +// TODO: remove inline fragment export const UserProfileQuery = graphql` query UserProfileQuery { me { profile { - ...ProfileItemFragment + ...ProfileItemInlineFragment } } } diff --git a/packages/components/package.json b/packages/components/package.json index 82b0315a..2e8f17f3 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,7 +1,7 @@ { "name": "@baseapp-frontend/components", "description": "BaseApp components modules such as comments, notifications, messages, and more.", - "version": "0.0.19", + "version": "0.0.20", "main": "./index.ts", "types": "dist/index.d.ts", "sideEffects": false, diff --git a/packages/components/schema.graphql b/packages/components/schema.graphql index c6e8cc4e..67b3abdb 100644 --- a/packages/components/schema.graphql +++ b/packages/components/schema.graphql @@ -208,6 +208,7 @@ interface ChatRoomsInterface { """Ordering""" orderBy: String profileId: String + unreadMessages: Boolean ): ChatRoomConnection unreadMessagesCount: Int } @@ -538,6 +539,7 @@ type Message implements Node { extraData: JSONString pk: Int! actionObject: Node + isRead(profileId: ID): Boolean } type MessageConnection { @@ -942,6 +944,7 @@ type Profile implements Node & PermissionsInterface & PageInterface & FollowsInt """Ordering""" orderBy: String profileId: String + unreadMessages: Boolean ): ChatRoomConnection unreadMessagesCount: Int pk: Int! diff --git a/packages/design-system/CHANGELOG.md b/packages/design-system/CHANGELOG.md index fdd5bc21..cc81a5f5 100644 --- a/packages/design-system/CHANGELOG.md +++ b/packages/design-system/CHANGELOG.md @@ -1,12 +1,22 @@ # @baseapp-frontend/design-system +## 0.0.21 + +### Patch Changes + +- Change `SearchBar` to use `withController`. +- Add `illustrations` icons. +- Remove `NoMessagesIcon` icon. +- Updated dependencies + - @baseapp-frontend/utils@3.0.4 + ## 0.0.20 ### Patch Changes -- Create `Searchbar` component. -- Add `NoMessagesIcon` icon. -- Export `PureTextFieldProps` type. +- Create `Searchbar` component. +- Add `NoMessagesIcon` icon. +- Export `PureTextFieldProps` type. ## 0.0.19 diff --git a/packages/design-system/components/Searchbar/types.ts b/packages/design-system/components/Searchbar/types.ts deleted file mode 100644 index 55577a62..00000000 --- a/packages/design-system/components/Searchbar/types.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { TransitionStartFunction } from 'react' - -import type { TextFieldProps } from '../inputs/TextField/types' - -export type SearchbarProps = TextFieldProps & { - isPending: boolean - refetch: any - startTransition: TransitionStartFunction -} diff --git a/packages/design-system/components/icons/NoMessagesIcon/index.tsx b/packages/design-system/components/icons/NoMessagesIcon/index.tsx deleted file mode 100644 index c8c1c2e1..00000000 --- a/packages/design-system/components/icons/NoMessagesIcon/index.tsx +++ /dev/null @@ -1,110 +0,0 @@ -import { FC } from 'react' - -import { SvgIcon, SvgIconProps } from '@mui/material' - -const NoMessagesIcon: FC = ({ sx, ...props }) => ( - - - - - - - - - - - - - - - - - - - - - - - - - - - -) - -export default NoMessagesIcon diff --git a/packages/design-system/components/icons/index.ts b/packages/design-system/components/icons/index.ts index bebcca89..99e922be 100644 --- a/packages/design-system/components/icons/index.ts +++ b/packages/design-system/components/icons/index.ts @@ -14,7 +14,6 @@ export { default as SendMessageIcon } from './SendMessageIcon' export { default as TrashCanIcon } from './TrashCanIcon' export { default as MenuIcon } from './MenuIcon' export { default as ChevronIcon } from './ChevronIcon' -export { default as NoMessagesIcon } from './NoMessagesIcon' export { default as NotificationBellIcon } from './NotificationBellIcon' export { default as OutlinedEditIcon } from './OutlinedEditIcon' export { default as ShareIcon } from './ShareIcon' diff --git a/packages/design-system/components/illustrations/ABTestingImage/index.tsx b/packages/design-system/components/illustrations/ABTestingImage/index.tsx new file mode 100644 index 00000000..98b9efc6 --- /dev/null +++ b/packages/design-system/components/illustrations/ABTestingImage/index.tsx @@ -0,0 +1,70 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const ABTestingImage: FC = ({ sx, ...props }) => ( + + + + + + + + + + + + + + + + + +) + +export default ABTestingImage diff --git a/packages/design-system/components/illustrations/AboutUsImage/index.tsx b/packages/design-system/components/illustrations/AboutUsImage/index.tsx new file mode 100644 index 00000000..69e0e8ac --- /dev/null +++ b/packages/design-system/components/illustrations/AboutUsImage/index.tsx @@ -0,0 +1,82 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const AboutUsImage: FC = ({ sx, ...props }) => ( + + + + + + + + + + + + + + + + + + + + +) + +export default AboutUsImage diff --git a/packages/design-system/components/illustrations/AddProductsToCartImage/index.tsx b/packages/design-system/components/illustrations/AddProductsToCartImage/index.tsx new file mode 100644 index 00000000..70f2d4b6 --- /dev/null +++ b/packages/design-system/components/illustrations/AddProductsToCartImage/index.tsx @@ -0,0 +1,50 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const AddProductsToCartImage: FC = ({ sx, ...props }) => ( + + + + + + + + + + + + +) + +export default AddProductsToCartImage diff --git a/packages/design-system/components/illustrations/BeingCreativeImage/index.tsx b/packages/design-system/components/illustrations/BeingCreativeImage/index.tsx new file mode 100644 index 00000000..379562cd --- /dev/null +++ b/packages/design-system/components/illustrations/BeingCreativeImage/index.tsx @@ -0,0 +1,74 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const BeingCreativeImage: FC = ({ sx, ...props }) => ( + + + + + + + + + + + + + + + + + + +) + +export default BeingCreativeImage diff --git a/packages/design-system/components/illustrations/BringSolutionsImage/index.tsx b/packages/design-system/components/illustrations/BringSolutionsImage/index.tsx new file mode 100644 index 00000000..ce10296d --- /dev/null +++ b/packages/design-system/components/illustrations/BringSolutionsImage/index.tsx @@ -0,0 +1,58 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const BringSolutionsImage: FC = ({ sx, ...props }) => ( + + + + + + + + + + + + + + +) + +export default BringSolutionsImage diff --git a/packages/design-system/components/illustrations/BusinessDealImage/index.tsx b/packages/design-system/components/illustrations/BusinessDealImage/index.tsx new file mode 100644 index 00000000..5ae02e4a --- /dev/null +++ b/packages/design-system/components/illustrations/BusinessDealImage/index.tsx @@ -0,0 +1,62 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const BusinessDealImage: FC = ({ sx, ...props }) => ( + + + + + + + + + + + + + + + +) + +export default BusinessDealImage diff --git a/packages/design-system/components/illustrations/ChartsImage/index.tsx b/packages/design-system/components/illustrations/ChartsImage/index.tsx new file mode 100644 index 00000000..e9c627d3 --- /dev/null +++ b/packages/design-system/components/illustrations/ChartsImage/index.tsx @@ -0,0 +1,94 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const ChartsImage: FC = ({ sx, ...props }) => ( + + + + + + + + + + + + + + + + + + + + + + + +) + +export default ChartsImage diff --git a/packages/design-system/components/illustrations/ClickbaitImage/index.tsx b/packages/design-system/components/illustrations/ClickbaitImage/index.tsx new file mode 100644 index 00000000..b5b963f3 --- /dev/null +++ b/packages/design-system/components/illustrations/ClickbaitImage/index.tsx @@ -0,0 +1,118 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const ClickbaitImage: FC = ({ sx, ...props }) => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +) + +export default ClickbaitImage diff --git a/packages/design-system/components/illustrations/CodingImage/index.tsx b/packages/design-system/components/illustrations/CodingImage/index.tsx new file mode 100644 index 00000000..90e76f85 --- /dev/null +++ b/packages/design-system/components/illustrations/CodingImage/index.tsx @@ -0,0 +1,50 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const CodingImage: FC = ({ sx, ...props }) => ( + + + + + + + + + + + + +) + +export default CodingImage diff --git a/packages/design-system/components/illustrations/ComingSoonImage/index.tsx b/packages/design-system/components/illustrations/ComingSoonImage/index.tsx new file mode 100644 index 00000000..7cefebc1 --- /dev/null +++ b/packages/design-system/components/illustrations/ComingSoonImage/index.tsx @@ -0,0 +1,78 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const ComingSoonImage: FC = ({ sx, ...props }) => ( + + + + + + + + + + + + + + + + + + + +) + +export default ComingSoonImage diff --git a/packages/design-system/components/illustrations/DesignThinkingImage/index.tsx b/packages/design-system/components/illustrations/DesignThinkingImage/index.tsx new file mode 100644 index 00000000..082fe099 --- /dev/null +++ b/packages/design-system/components/illustrations/DesignThinkingImage/index.tsx @@ -0,0 +1,118 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const DesignThinkingImage: FC = ({ sx, ...props }) => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +) + +export default DesignThinkingImage diff --git a/packages/design-system/components/illustrations/DigitalAdsPerformanceImage/index.tsx b/packages/design-system/components/illustrations/DigitalAdsPerformanceImage/index.tsx new file mode 100644 index 00000000..0177d218 --- /dev/null +++ b/packages/design-system/components/illustrations/DigitalAdsPerformanceImage/index.tsx @@ -0,0 +1,70 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const DigitalAdsPerformanceImage: FC = ({ sx, ...props }) => ( + + + + + + + + + + + + + + + + + +) + +export default DigitalAdsPerformanceImage diff --git a/packages/design-system/components/illustrations/DownloadingImage/index.tsx b/packages/design-system/components/illustrations/DownloadingImage/index.tsx new file mode 100644 index 00000000..48b9e211 --- /dev/null +++ b/packages/design-system/components/illustrations/DownloadingImage/index.tsx @@ -0,0 +1,78 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const DownloadingImage: FC = ({ sx, ...props }) => ( + + + + + + + + + + + + + + + + + + + +) + +export default DownloadingImage diff --git a/packages/design-system/components/illustrations/DrawingWIthTabletImage/index.tsx b/packages/design-system/components/illustrations/DrawingWIthTabletImage/index.tsx new file mode 100644 index 00000000..17d315e0 --- /dev/null +++ b/packages/design-system/components/illustrations/DrawingWIthTabletImage/index.tsx @@ -0,0 +1,42 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const DrawingWIthTabletImage: FC = ({ sx, ...props }) => ( + + + + + + + + + + +) + +export default DrawingWIthTabletImage diff --git a/packages/design-system/components/illustrations/FixingBugsImage/index.tsx b/packages/design-system/components/illustrations/FixingBugsImage/index.tsx new file mode 100644 index 00000000..3bcbb9bd --- /dev/null +++ b/packages/design-system/components/illustrations/FixingBugsImage/index.tsx @@ -0,0 +1,106 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const FixingBugsImage: FC = ({ sx, ...props }) => ( + + + + + + + + + + + + + + + + + + + + + + + + + + +) + +export default FixingBugsImage diff --git a/packages/design-system/components/illustrations/GetInspiredImage/index.tsx b/packages/design-system/components/illustrations/GetInspiredImage/index.tsx new file mode 100644 index 00000000..bada14d8 --- /dev/null +++ b/packages/design-system/components/illustrations/GetInspiredImage/index.tsx @@ -0,0 +1,58 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const GetInspiredImage: FC = ({ sx, ...props }) => ( + + + + + + + + + + + + + + +) + +export default GetInspiredImage diff --git a/packages/design-system/components/illustrations/GiftingOnlineImage/index.tsx b/packages/design-system/components/illustrations/GiftingOnlineImage/index.tsx new file mode 100644 index 00000000..7b30d11b --- /dev/null +++ b/packages/design-system/components/illustrations/GiftingOnlineImage/index.tsx @@ -0,0 +1,42 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const GiftingOnlineImage: FC = ({ sx, ...props }) => ( + + + + + + + + + + +) + +export default GiftingOnlineImage diff --git a/packages/design-system/components/illustrations/InterfaceTestingImage/index.tsx b/packages/design-system/components/illustrations/InterfaceTestingImage/index.tsx new file mode 100644 index 00000000..8b3c8392 --- /dev/null +++ b/packages/design-system/components/illustrations/InterfaceTestingImage/index.tsx @@ -0,0 +1,46 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const InterfaceTestingImage: FC = ({ sx, ...props }) => ( + + + + + + + + + + + +) + +export default InterfaceTestingImage diff --git a/packages/design-system/components/illustrations/InvestingTestingImage/index.tsx b/packages/design-system/components/illustrations/InvestingTestingImage/index.tsx new file mode 100644 index 00000000..f8e8a571 --- /dev/null +++ b/packages/design-system/components/illustrations/InvestingTestingImage/index.tsx @@ -0,0 +1,54 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const InvestingTestingImage: FC = ({ sx, ...props }) => ( + + + + + + + + + + + + + +) + +export default InvestingTestingImage diff --git a/packages/design-system/components/illustrations/ListeningFeedbackImage/index.tsx b/packages/design-system/components/illustrations/ListeningFeedbackImage/index.tsx new file mode 100644 index 00000000..400e10f9 --- /dev/null +++ b/packages/design-system/components/illustrations/ListeningFeedbackImage/index.tsx @@ -0,0 +1,66 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const ListeningFeedbackImage: FC = ({ sx, ...props }) => ( + + + + + + + + + + + + + + + + +) + +export default ListeningFeedbackImage diff --git a/packages/design-system/components/illustrations/LoadingImage/index.tsx b/packages/design-system/components/illustrations/LoadingImage/index.tsx new file mode 100644 index 00000000..74989f02 --- /dev/null +++ b/packages/design-system/components/illustrations/LoadingImage/index.tsx @@ -0,0 +1,114 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const LoadingImage: FC = ({ sx, ...props }) => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + +) + +export default LoadingImage diff --git a/packages/design-system/components/illustrations/MarketingTargetImage/index.tsx b/packages/design-system/components/illustrations/MarketingTargetImage/index.tsx new file mode 100644 index 00000000..134144ef --- /dev/null +++ b/packages/design-system/components/illustrations/MarketingTargetImage/index.tsx @@ -0,0 +1,106 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const MarketingTargetImage: FC = ({ sx, ...props }) => ( + + + + + + + + + + + + + + + + + + + + + + + + + + +) + +export default MarketingTargetImage diff --git a/packages/design-system/components/illustrations/ModularCodingApplicationImage/index.tsx b/packages/design-system/components/illustrations/ModularCodingApplicationImage/index.tsx new file mode 100644 index 00000000..99c21c4d --- /dev/null +++ b/packages/design-system/components/illustrations/ModularCodingApplicationImage/index.tsx @@ -0,0 +1,86 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const ModularCodingApplicationImage: FC = ({ sx, ...props }) => ( + + + + + + + + + + + + + + + + + + + + + +) + +export default ModularCodingApplicationImage diff --git a/packages/design-system/components/illustrations/NewsletterImage/index.tsx b/packages/design-system/components/illustrations/NewsletterImage/index.tsx new file mode 100644 index 00000000..1412bc46 --- /dev/null +++ b/packages/design-system/components/illustrations/NewsletterImage/index.tsx @@ -0,0 +1,38 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const NewsletterImage: FC = ({ sx, ...props }) => ( + + + + + + + + + +) + +export default NewsletterImage diff --git a/packages/design-system/components/illustrations/OfficeDeskImage/index.tsx b/packages/design-system/components/illustrations/OfficeDeskImage/index.tsx new file mode 100644 index 00000000..ffa4f4b9 --- /dev/null +++ b/packages/design-system/components/illustrations/OfficeDeskImage/index.tsx @@ -0,0 +1,54 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const OfficeDeskImage: FC = ({ sx, ...props }) => ( + + + + + + + + + + + + + +) + +export default OfficeDeskImage diff --git a/packages/design-system/components/illustrations/OverworkedEmployee/index.tsx b/packages/design-system/components/illustrations/OverworkedEmployee/index.tsx new file mode 100644 index 00000000..834c4131 --- /dev/null +++ b/packages/design-system/components/illustrations/OverworkedEmployee/index.tsx @@ -0,0 +1,50 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const OverworkedEmployee: FC = ({ sx, ...props }) => ( + + + + + + + + + + + + +) + +export default OverworkedEmployee diff --git a/packages/design-system/components/illustrations/PageUnderConstructionImage/index.tsx b/packages/design-system/components/illustrations/PageUnderConstructionImage/index.tsx new file mode 100644 index 00000000..c20c2452 --- /dev/null +++ b/packages/design-system/components/illustrations/PageUnderConstructionImage/index.tsx @@ -0,0 +1,50 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const PageUnderConstructionImage: FC = ({ sx, ...props }) => ( + + + + + + + + + + + + +) + +export default PageUnderConstructionImage diff --git a/packages/design-system/components/illustrations/PaymentWithCardImage/index.tsx b/packages/design-system/components/illustrations/PaymentWithCardImage/index.tsx new file mode 100644 index 00000000..f31f4533 --- /dev/null +++ b/packages/design-system/components/illustrations/PaymentWithCardImage/index.tsx @@ -0,0 +1,78 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const PaymentWithCardImage: FC = ({ sx, ...props }) => ( + + + + + + + + + + + + + + + + + + + +) + +export default PaymentWithCardImage diff --git a/packages/design-system/components/illustrations/ProtectPrivacyImage/index.tsx b/packages/design-system/components/illustrations/ProtectPrivacyImage/index.tsx new file mode 100644 index 00000000..553a520e --- /dev/null +++ b/packages/design-system/components/illustrations/ProtectPrivacyImage/index.tsx @@ -0,0 +1,42 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const ProtectPrivacyImage: FC = ({ sx, ...props }) => ( + + + + + + + + + + +) + +export default ProtectPrivacyImage diff --git a/packages/design-system/components/illustrations/SearchingImage/index.tsx b/packages/design-system/components/illustrations/SearchingImage/index.tsx new file mode 100644 index 00000000..c8a7d38d --- /dev/null +++ b/packages/design-system/components/illustrations/SearchingImage/index.tsx @@ -0,0 +1,42 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const SearchingImage: FC = ({ sx, ...props }) => ( + + + + + + + + + + +) + +export default SearchingImage diff --git a/packages/design-system/components/illustrations/ShareImage/index.tsx b/packages/design-system/components/illustrations/ShareImage/index.tsx new file mode 100644 index 00000000..08535bbb --- /dev/null +++ b/packages/design-system/components/illustrations/ShareImage/index.tsx @@ -0,0 +1,46 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const ShareImage: FC = ({ sx, ...props }) => ( + + + + + + + + + + + +) + +export default ShareImage diff --git a/packages/design-system/components/illustrations/SocialMediaDiscussionImage/index.tsx b/packages/design-system/components/illustrations/SocialMediaDiscussionImage/index.tsx new file mode 100644 index 00000000..31685be0 --- /dev/null +++ b/packages/design-system/components/illustrations/SocialMediaDiscussionImage/index.tsx @@ -0,0 +1,110 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const SocialMediaDiscussionImage: FC = ({ sx, ...props }) => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + +) + +export default SocialMediaDiscussionImage diff --git a/packages/design-system/components/illustrations/SuccessImage/index.tsx b/packages/design-system/components/illustrations/SuccessImage/index.tsx new file mode 100644 index 00000000..94ec1298 --- /dev/null +++ b/packages/design-system/components/illustrations/SuccessImage/index.tsx @@ -0,0 +1,50 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const SuccessImage: FC = ({ sx, ...props }) => ( + + + + + + + + + + + + +) + +export default SuccessImage diff --git a/packages/design-system/components/illustrations/TrophyAwardsImage/index.tsx b/packages/design-system/components/illustrations/TrophyAwardsImage/index.tsx new file mode 100644 index 00000000..09c94a7a --- /dev/null +++ b/packages/design-system/components/illustrations/TrophyAwardsImage/index.tsx @@ -0,0 +1,46 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const TrophyAwardsImage: FC = ({ sx, ...props }) => ( + + + + + + + + + + + +) + +export default TrophyAwardsImage diff --git a/packages/design-system/components/illustrations/VideoConferenceImage/index.tsx b/packages/design-system/components/illustrations/VideoConferenceImage/index.tsx new file mode 100644 index 00000000..56f9489b --- /dev/null +++ b/packages/design-system/components/illustrations/VideoConferenceImage/index.tsx @@ -0,0 +1,130 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const VideoConferenceImage: FC = ({ sx, ...props }) => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +) + +export default VideoConferenceImage diff --git a/packages/design-system/components/illustrations/VirtualRealityImage/index.tsx b/packages/design-system/components/illustrations/VirtualRealityImage/index.tsx new file mode 100644 index 00000000..79c5ae9f --- /dev/null +++ b/packages/design-system/components/illustrations/VirtualRealityImage/index.tsx @@ -0,0 +1,90 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const VirtualRealityImage: FC = ({ sx, ...props }) => ( + + + + + + + + + + + + + + + + + + + + + + +) + +export default VirtualRealityImage diff --git a/packages/design-system/components/illustrations/WeAreHiringImage/index.tsx b/packages/design-system/components/illustrations/WeAreHiringImage/index.tsx new file mode 100644 index 00000000..a7e45d82 --- /dev/null +++ b/packages/design-system/components/illustrations/WeAreHiringImage/index.tsx @@ -0,0 +1,110 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const WeAreHiringImage: FC = ({ sx, ...props }) => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + +) + +export default WeAreHiringImage diff --git a/packages/design-system/components/illustrations/WeGotAProblemImage/index.tsx b/packages/design-system/components/illustrations/WeGotAProblemImage/index.tsx new file mode 100644 index 00000000..d04872a0 --- /dev/null +++ b/packages/design-system/components/illustrations/WeGotAProblemImage/index.tsx @@ -0,0 +1,118 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const WeGotAProblemImage: FC = ({ sx, ...props }) => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +) + +export default WeGotAProblemImage diff --git a/packages/design-system/components/illustrations/WelcomeImage/index.tsx b/packages/design-system/components/illustrations/WelcomeImage/index.tsx new file mode 100644 index 00000000..cb86fd62 --- /dev/null +++ b/packages/design-system/components/illustrations/WelcomeImage/index.tsx @@ -0,0 +1,86 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const WelcomeImage: FC = ({ sx, ...props }) => ( + + + + + + + + + + + + + + + + + + + + + +) + +export default WelcomeImage diff --git a/packages/design-system/components/illustrations/WorkFromHomeImage/index.tsx b/packages/design-system/components/illustrations/WorkFromHomeImage/index.tsx new file mode 100644 index 00000000..2cf63231 --- /dev/null +++ b/packages/design-system/components/illustrations/WorkFromHomeImage/index.tsx @@ -0,0 +1,42 @@ +import { FC } from 'react' + +import { SvgIcon, SvgIconProps } from '@mui/material' + +const WorkFromHomeImage: FC = ({ sx, ...props }) => ( + + + + + + + + + + +) + +export default WorkFromHomeImage diff --git a/packages/design-system/components/illustrations/__storybook__/Illustrations.mdx b/packages/design-system/components/illustrations/__storybook__/Illustrations.mdx new file mode 100644 index 00000000..c91b3a85 --- /dev/null +++ b/packages/design-system/components/illustrations/__storybook__/Illustrations.mdx @@ -0,0 +1,27 @@ +import { Meta } from '@storybook/blocks' + +import * as AllImages from '..' + + + +# Illustrations + +
+ {Object.entries(AllImages).map(([imageName, ImageComponent]) => ( +
+ +
+ {imageName + .replace(/([A-Z])/g, ' $1') + .replace('Image', '') + .trim()} +
+
+ ))} +
diff --git a/packages/design-system/components/illustrations/index.ts b/packages/design-system/components/illustrations/index.ts new file mode 100644 index 00000000..e380c55f --- /dev/null +++ b/packages/design-system/components/illustrations/index.ts @@ -0,0 +1,40 @@ +export { default as ABTestingImage } from './ABTestingImage' +export { default as AboutUsImage } from './AboutUsImage' +export { default as AddProductsToCartImage } from './AddProductsToCartImage' +export { default as BeingCreativeImage } from './BeingCreativeImage' +export { default as BringSolutionsImage } from './BringSolutionsImage' +export { default as BusinessDealImage } from './BusinessDealImage' +export { default as ChartsImage } from './ChartsImage' +export { default as ClickbaitImage } from './ClickbaitImage' +export { default as CodingImage } from './CodingImage' +export { default as ComingSoonImage } from './ComingSoonImage' +export { default as DesignThinkingImage } from './DesignThinkingImage' +export { default as DigitalAdsPerformanceImage } from './DigitalAdsPerformanceImage' +export { default as DownloadingImage } from './DownloadingImage' +export { default as DrawingWIthTabletImage } from './DrawingWIthTabletImage' +export { default as FixingBugsImage } from './FixingBugsImage' +export { default as GetInspiredImage } from './GetInspiredImage' +export { default as GiftingOnlineImage } from './GiftingOnlineImage' +export { default as InterfaceTestingImage } from './InterfaceTestingImage' +export { default as InvestingTestingImage } from './InvestingTestingImage' +export { default as ListeningFeedbackImage } from './ListeningFeedbackImage' +export { default as LoadingImage } from './LoadingImage' +export { default as MarketingTargetImage } from './MarketingTargetImage' +export { default as ModularCodingApplicationImage } from './ModularCodingApplicationImage' +export { default as NewsletterImage } from './NewsletterImage' +export { default as OfficeDeskImage } from './OfficeDeskImage' +export { default as OverworkedEmployee } from './OverworkedEmployee' +export { default as PageUnderConstructionImage } from './PageUnderConstructionImage' +export { default as PaymentWithCardImage } from './PaymentWithCardImage' +export { default as ProtectPrivacyImage } from './ProtectPrivacyImage' +export { default as SearchingImage } from './SearchingImage' +export { default as ShareImage } from './ShareImage' +export { default as SocialMediaDiscussionImage } from './SocialMediaDiscussionImage' +export { default as SuccessImage } from './SuccessImage' +export { default as TrophyAwardsImage } from './TrophyAwardsImage' +export { default as VideoConferenceImage } from './VideoConferenceImage' +export { default as VirtualRealityImage } from './VirtualRealityImage' +export { default as WeAreHiringImage } from './WeAreHiringImage' +export { default as WeGotAProblemImage } from './WeGotAProblemImage' +export { default as WelcomeImage } from './WelcomeImage' +export { default as WorkFromHomeImage } from './WorkFromHomeImage' diff --git a/packages/design-system/components/Searchbar/__storybook__/stories.tsx b/packages/design-system/components/inputs/Searchbar/__storybook__/stories.tsx similarity index 50% rename from packages/design-system/components/Searchbar/__storybook__/stories.tsx rename to packages/design-system/components/inputs/Searchbar/__storybook__/stories.tsx index e847fce8..c8c8cec0 100644 --- a/packages/design-system/components/Searchbar/__storybook__/stories.tsx +++ b/packages/design-system/components/inputs/Searchbar/__storybook__/stories.tsx @@ -1,5 +1,3 @@ -import { useTransition } from 'react' - import { Meta, StoryObj } from '@storybook/react' import Searchbar from '..' @@ -14,18 +12,18 @@ export default { control: 'boolean', description: 'Loading state provided by the transition hook.', }, - refetch: { - action: 'refetch query', - description: 'The refetch function provided by the graphql query hook.', + onClear: { + action: 'clear search', + description: 'Function to clear the search input.', table: { type: { summary: 'VoidFunction' }, }, }, - startTransition: { - action: 'start transition', - description: 'The transition function provided by the transition hook.', + onChange: { + action: 'change input', + description: 'Function to handle input change.', table: { - type: { summary: 'VoidFunction' }, + type: { summary: 'NonUndefined' }, }, }, }, @@ -33,17 +31,8 @@ export default { type Story = StoryObj -const SearchbarTemplate = (args: any) => { - const [, startTransition] = useTransition() - - const refetch = () => {} - - return -} - export const Default: Story = { args: { isPending: false, }, - render: (args) => , } diff --git a/packages/design-system/components/Searchbar/index.tsx b/packages/design-system/components/inputs/Searchbar/index.tsx similarity index 63% rename from packages/design-system/components/Searchbar/index.tsx rename to packages/design-system/components/inputs/Searchbar/index.tsx index 81924917..1e456dce 100644 --- a/packages/design-system/components/Searchbar/index.tsx +++ b/packages/design-system/components/inputs/Searchbar/index.tsx @@ -1,59 +1,38 @@ 'use client' -import { ChangeEvent, FC } from 'react' +import { FC } from 'react' -import { useDebounce } from '@baseapp-frontend/utils' +import { withController } from '@baseapp-frontend/utils' import { CircularProgress, InputAdornment } from '@mui/material' import { Box } from '@mui/system' -import { useForm } from 'react-hook-form' -import Iconify from '../Iconify' -import { IconButton } from '../buttons' -import { TextField } from '../inputs' +import Iconify from '../../Iconify' +import { IconButton } from '../../buttons' +import { PureTextField } from '../TextField' import { SearchbarProps } from './types' const Searchbar: FC = ({ - startTransition, - refetch, + onClear, + onChange, isPending, sx, InputProps, variant = 'filled', ...props + // eslint-disable-next-line arrow-body-style }) => { - const { control, watch, reset } = useForm({ defaultValues: { search: '' } }) - - const handleChange = (e: ChangeEvent) => { - const value = e.target.value || '' - startTransition(() => { - refetch({ q: value }) - }) - } - - const handleReset = () => { - startTransition(() => { - reset() - refetch({ q: '' }) - }) - } - const watchSearch = watch('search') - - const { debouncedFunction: handleDebouncedChange } = useDebounce(handleChange) - return ( - @@ -75,8 +54,8 @@ const Searchbar: FC = ({ ), endAdornment: ( - {watchSearch ? ( - + {onClear && props.value ? ( + ) : ( @@ -103,4 +82,4 @@ const Searchbar: FC = ({ ) } -export default Searchbar +export default withController(Searchbar, { shouldDebounce: true }) diff --git a/packages/design-system/components/inputs/Searchbar/types.ts b/packages/design-system/components/inputs/Searchbar/types.ts new file mode 100644 index 00000000..f8892283 --- /dev/null +++ b/packages/design-system/components/inputs/Searchbar/types.ts @@ -0,0 +1,9 @@ +import type { NonUndefined } from 'react-hook-form' + +import type { TextFieldProps } from '../TextField/types' + +export type SearchbarProps = Omit & { + isPending: boolean + onClear?: () => void + onChange: NonUndefined +} diff --git a/packages/design-system/components/inputs/index.ts b/packages/design-system/components/inputs/index.ts index 3a4f5fe4..0992a866 100644 --- a/packages/design-system/components/inputs/index.ts +++ b/packages/design-system/components/inputs/index.ts @@ -1,3 +1,6 @@ +export { default as Searchbar } from './Searchbar' +export type * from './Searchbar/types' + export { default as SocialTextField } from './SocialTextField' export type * from './SocialTextField/types' diff --git a/packages/design-system/index.ts b/packages/design-system/index.ts index 3a445ea4..ca28fedd 100644 --- a/packages/design-system/index.ts +++ b/packages/design-system/index.ts @@ -25,6 +25,7 @@ export * from './components/dialogs' export * from './components/displays' export * from './components/drawers' export * from './components/icons' +export * from './components/illustrations' export * from './components/inputs' export * from './components/typographies' @@ -34,9 +35,6 @@ export type * from './components/Iconify/types' export { default as Scrollbar } from './components/Scrollbar' export type * from './components/Scrollbar/types' -export { default as Searchbar } from './components/Searchbar' -export type * from './components/Searchbar/types' - export { default as ProjectLogo } from './components/ProjectLogo' export type * from './components/ProjectLogo/types' diff --git a/packages/design-system/package.json b/packages/design-system/package.json index eec0293d..4b21e0cc 100644 --- a/packages/design-system/package.json +++ b/packages/design-system/package.json @@ -1,7 +1,7 @@ { "name": "@baseapp-frontend/design-system", "description": "Design System components and configurations.", - "version": "0.0.20", + "version": "0.0.21", "main": "./index.ts", "types": "dist/index.d.ts", "sideEffects": false, diff --git a/packages/graphql/CHANGELOG.md b/packages/graphql/CHANGELOG.md index 02fff82e..1dcf6213 100644 --- a/packages/graphql/CHANGELOG.md +++ b/packages/graphql/CHANGELOG.md @@ -1,5 +1,12 @@ # @baseapp-frontend/graphql +## 1.1.12 + +### Patch Changes + +- Updated dependencies + - @baseapp-frontend/utils@3.0.4 + ## 1.1.11 ### Patch Changes diff --git a/packages/graphql/package.json b/packages/graphql/package.json index bacbee92..36427102 100644 --- a/packages/graphql/package.json +++ b/packages/graphql/package.json @@ -1,7 +1,7 @@ { "name": "@baseapp-frontend/graphql", "description": "GraphQL configurations and utilities", - "version": "1.1.11", + "version": "1.1.12", "main": "./index.ts", "types": "dist/index.d.ts", "sideEffects": false, diff --git a/packages/provider/CHANGELOG.md b/packages/provider/CHANGELOG.md index 6537274d..2ccf0f41 100644 --- a/packages/provider/CHANGELOG.md +++ b/packages/provider/CHANGELOG.md @@ -1,5 +1,12 @@ # @baseapp-frontend/provider +## 2.0.5 + +### Patch Changes + +- Updated dependencies + - @baseapp-frontend/utils@3.0.4 + ## 2.0.4 ### Patch Changes diff --git a/packages/provider/package.json b/packages/provider/package.json index c1d64f33..635415d4 100644 --- a/packages/provider/package.json +++ b/packages/provider/package.json @@ -1,7 +1,7 @@ { "name": "@baseapp-frontend/provider", "description": "Providers for React Query and Emotion.", - "version": "2.0.4", + "version": "2.0.5", "main": "./index.ts", "types": "dist/index.d.ts", "sideEffects": false, diff --git a/packages/utils/CHANGELOG.md b/packages/utils/CHANGELOG.md index 53d9f276..b73b0163 100644 --- a/packages/utils/CHANGELOG.md +++ b/packages/utils/CHANGELOG.md @@ -1,5 +1,11 @@ # @baseapp-frontend/utils +## 3.0.4 + +### Patch Changes + +- `withController` have an option for debounce the `handleChange` function provided. + ## 3.0.3 ### Patch Changes diff --git a/packages/utils/functions/date/index.ts b/packages/utils/functions/date/index.ts index 85186a72..b3e95480 100644 --- a/packages/utils/functions/date/index.ts +++ b/packages/utils/functions/date/index.ts @@ -1,6 +1,6 @@ import { DateTime } from 'luxon' -import { DATE_FORMAT } from '../../constants/date' +import { DATE_FORMAT, TIME_FORMAT } from '../../constants/date' import { FormatDateFromApiOptions, FormatDateOptions, @@ -79,3 +79,26 @@ export const datesDontHaveSameDay = (date1: string, date2: string) => { return !dt1.hasSame(dt2, 'day') } + +export const formatDateWithDiffNow = (date?: string | null) => { + if (!date) return '' + const dateTime = DateTime.fromISO(date) + if (!dateTime.isValid) return '' + + if (isToday(date)) return formatDateFromApi(date, { toFormat: TIME_FORMAT[2] }) + if (isYesterday(date)) return 'Yesterday' + + const diff = dateTime.diffNow(['years', 'months', 'weeks', 'days']).toObject() + + if (diff.months && Math.abs(diff.months) > 0) { + if (Math.abs(diff.months) > 1) return `${Math.abs(diff.months).toFixed(0)} months ago` + return '1 month ago' + } + if (diff.weeks && Math.abs(diff.weeks) > 0) { + if (Math.abs(diff.weeks) > 1) return `${Math.abs(diff.weeks).toFixed(0)} weeks ago` + return '1 week ago' + } + if (diff.days && Math.abs(diff.days) > 0) return `${Math.abs(diff.days).toFixed(0)} days ago` + + return formatDateFromApi(date, { toFormat: DATE_FORMAT[2] }) +} diff --git a/packages/utils/functions/form/withController/index.tsx b/packages/utils/functions/form/withController/index.tsx index 1037bdb3..18a03372 100644 --- a/packages/utils/functions/form/withController/index.tsx +++ b/packages/utils/functions/form/withController/index.tsx @@ -1,15 +1,24 @@ 'use client' -import type { ChangeEventHandler, FC, FocusEventHandler } from 'react' +import { ChangeEventHandler, FC, FocusEventHandler } from 'react' import { Controller } from 'react-hook-form' -import type { WithControllerProps } from './types' +import useDebounce from '../../../hooks/useDebounce' +import type { DebouncedFunction, WithControllerProps } from './types' -function withController(Component: FC) { +function withController(Component: FC, { shouldDebounce = false, debounceTime = 500 } = {}) { return ({ name, control, helperText, ...props }: WithControllerProps) => { if (control) { const { onChange, onBlur, ...restOfTheProps } = props + const onChangeWithFallback = onChange ?? (() => {}) + const { debouncedFunction: debouncedOnChange } = useDebounce( + onChangeWithFallback, + { + debounceTime, + }, + ) + return ( (Component: FC) { event, ) => { field.onChange(event) - onChange?.(event) + if (onChange && shouldDebounce) { + debouncedOnChange(event) + } else { + onChange?.(event) + } } const handleOnBlur: FocusEventHandler = ( event, diff --git a/packages/utils/functions/form/withController/types.ts b/packages/utils/functions/form/withController/types.ts index f36d0dbc..befe0b25 100644 --- a/packages/utils/functions/form/withController/types.ts +++ b/packages/utils/functions/form/withController/types.ts @@ -1,5 +1,7 @@ import { ChangeEventHandler, FocusEventHandler } from 'react' +import type { NonUndefined } from 'react-hook-form' + import { FormControl } from '../../../types/form' type OptionalActions = { @@ -7,4 +9,6 @@ type OptionalActions = { onBlur?: (value?: any) => void | FocusEventHandler } +export type DebouncedFunction = NonUndefined + export type WithControllerProps = FormControl & T & OptionalActions diff --git a/packages/utils/package.json b/packages/utils/package.json index 2492182c..e7ad4902 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,7 +1,7 @@ { "name": "@baseapp-frontend/utils", "description": "Util functions, constants and types.", - "version": "3.0.3", + "version": "3.0.4", "main": "./index.ts", "types": "dist/index.d.ts", "sideEffects": false, diff --git a/packages/wagtail/CHANGELOG.md b/packages/wagtail/CHANGELOG.md index 766946b2..456b9b93 100644 --- a/packages/wagtail/CHANGELOG.md +++ b/packages/wagtail/CHANGELOG.md @@ -1,5 +1,14 @@ # @baseapp-frontend/wagtail +## 1.0.3 + +### Patch Changes + +- Updated dependencies + - @baseapp-frontend/design-system@0.0.21 + - @baseapp-frontend/graphql@1.1.12 + - @baseapp-frontend/utils@3.0.4 + ## 1.0.2 ### Patch Changes diff --git a/packages/wagtail/package.json b/packages/wagtail/package.json index 82cb60e1..92f3c9c1 100644 --- a/packages/wagtail/package.json +++ b/packages/wagtail/package.json @@ -1,7 +1,7 @@ { "name": "@baseapp-frontend/wagtail", "description": "BaseApp Wagtail", - "version": "1.0.2", + "version": "1.0.3", "main": "./index.ts", "types": "dist/index.d.ts", "sideEffects": false, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5b526130..33433bdb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10164,7 +10164,7 @@ snapshots: '@babel/generator@7.17.7': dependencies: - '@babel/types': 7.17.0 + '@babel/types': 7.26.0 jsesc: 2.5.2 source-map: 0.5.7