-
Unknown Route
-
{data.user.name}
+ <>
+
Studio
+
+
+
+
+
+
Hello
+
Hello
+
Hello
+
+
{data.user.userCompanies.map(userCompany => (
- {userCompany.company.name} : {userCompany.isOwner} :{' '}
+ {userCompany.company.name} :{' '}
+ {userCompany.isOwner ? 'true' : 'false'} :{' '}
{userCompany.Role.map(role => (
{role.name} :{' '}
@@ -63,6 +77,6 @@ export default function StudioIndex() {
))}
-
+ >
)
}
diff --git a/app/utils/user.ts b/app/utils/user.ts
index 0958e63..7592480 100644
--- a/app/utils/user.ts
+++ b/app/utils/user.ts
@@ -25,7 +25,7 @@ export function useUser() {
}
type Action = 'create' | 'read' | 'update' | 'delete'
-type Entity = 'user' | 'note'
+type Entity = 'user' | 'note' | 'company'
type Access = 'own' | 'any' | 'own,any' | 'any,own'
export type PermissionString =
| `${Action}:${Entity}`
diff --git a/package-lock.json b/package-lock.json
index 81aade4..f95cd31 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -15,7 +15,7 @@
"@epic-web/totp": "^1.1.1",
"@nasa-gcn/remix-seo": "^2.0.0",
"@paralleldrive/cuid2": "^2.2.2",
- "@prisma/client": "^5.10.0-dev.1",
+ "@prisma/client": "^5.9.1",
"@radix-ui/react-checkbox": "^1.0.4",
"@radix-ui/react-dialog": "^1.0.5",
"@radix-ui/react-dropdown-menu": "^2.0.6",
@@ -24,11 +24,11 @@
"@radix-ui/react-toast": "^1.1.5",
"@radix-ui/react-tooltip": "^1.0.7",
"@react-email/components": "0.0.14",
- "@remix-run/css-bundle": "^2.5.1",
- "@remix-run/express": "^2.5.1",
- "@remix-run/node": "^2.5.1",
- "@remix-run/react": "^2.5.1",
- "@remix-run/server-runtime": "^2.5.1",
+ "@remix-run/css-bundle": "^2.6.0",
+ "@remix-run/express": "^2.6.0",
+ "@remix-run/node": "^2.6.0",
+ "@remix-run/react": "^2.6.0",
+ "@remix-run/server-runtime": "^2.6.0",
"@sentry/profiling-node": "^1.3.5",
"@sentry/remix": "^7.99.0",
"address": "^2.0.1",
@@ -76,14 +76,14 @@
},
"devDependencies": {
"@faker-js/faker": "^8.4.0",
- "@playwright/test": "^1.41.1",
- "@remix-run/dev": "^2.5.1",
- "@remix-run/eslint-config": "^2.5.1",
- "@remix-run/serve": "^2.5.1",
- "@remix-run/testing": "^2.5.1",
+ "@playwright/test": "^1.41.2",
+ "@remix-run/dev": "^2.6.0",
+ "@remix-run/eslint-config": "^2.6.0",
+ "@remix-run/serve": "^2.6.0",
+ "@remix-run/testing": "^2.6.0",
"@sly-cli/sly": "^1.8.0",
"@testing-library/jest-dom": "^6.4.1",
- "@testing-library/react": "^14.2.0",
+ "@testing-library/react": "^14.2.1",
"@testing-library/user-event": "^14.5.2",
"@total-typescript/ts-reset": "^0.5.1",
"@types/bcryptjs": "^2.4.6",
@@ -95,9 +95,9 @@
"@types/fs-extra": "^11.0.4",
"@types/glob": "^8.1.0",
"@types/morgan": "^1.9.9",
- "@types/node": "^20.11.14",
+ "@types/node": "^20.11.16",
"@types/qrcode": "^1.5.5",
- "@types/react": "^18.2.50",
+ "@types/react": "^18.2.51",
"@types/react-dom": "^18.2.18",
"@types/set-cookie-parser": "^2.4.7",
"@types/source-map-support": "^0.5.10",
@@ -116,7 +116,7 @@
"prettier": "^3.2.4",
"prettier-plugin-sql": "^0.18.0",
"prettier-plugin-tailwindcss": "^0.5.11",
- "prisma": "^5.10.0-dev.1",
+ "prisma": "^5.9.1",
"remix-flat-routes": "^0.6.4",
"rimraf": "^5.0.5",
"tsx": "^4.7.0",
@@ -1987,12 +1987,12 @@
}
},
"node_modules/@playwright/test": {
- "version": "1.41.1",
- "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.41.1.tgz",
- "integrity": "sha512-9g8EWTjiQ9yFBXc6HjCWe41msLpxEX0KhmfmPl9RPLJdfzL4F0lg2BdJ91O9azFdl11y1pmpwdjBiSxvqc+btw==",
+ "version": "1.41.2",
+ "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.41.2.tgz",
+ "integrity": "sha512-qQB9h7KbibJzrDpkXkYvsmiDJK14FULCCZgEcoe2AvFAS64oCirWTwzTlAYEbKaRxWs5TFesE1Na6izMv3HfGg==",
"dev": true,
"dependencies": {
- "playwright": "1.41.1"
+ "playwright": "1.41.2"
},
"bin": {
"playwright": "cli.js"
@@ -2002,9 +2002,9 @@
}
},
"node_modules/@prisma/client": {
- "version": "5.10.0-dev.1",
- "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.10.0-dev.1.tgz",
- "integrity": "sha512-Y3BcweUn4+wpR+IB0HvssbVjubRLsPxUZhrSY1b6lJWkwUt0Db2W6bWYkRDEJBZzI9A8q5b463MJkrVRVNzZVg==",
+ "version": "5.9.1",
+ "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.9.1.tgz",
+ "integrity": "sha512-caSOnG4kxcSkhqC/2ShV7rEoWwd3XrftokxJqOCMVvia4NYV/TPtJlS9C2os3Igxw/Qyxumj9GBQzcStzECvtQ==",
"hasInstallScript": true,
"engines": {
"node": ">=16.13"
@@ -2019,22 +2019,22 @@
}
},
"node_modules/@prisma/debug": {
- "version": "5.10.0-dev.1",
- "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.10.0-dev.1.tgz",
- "integrity": "sha512-LZZI+iyw2gBQkxgEBD9OOf9YDPlvmHQI4GOruqAkEzHs+CCQKRWu/QiepppkLWLaj2INbncQJPiSTm5UOk7THw==",
+ "version": "5.9.1",
+ "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.9.1.tgz",
+ "integrity": "sha512-yAHFSFCg8KVoL0oRUno3m60GAjsUKYUDkQ+9BA2X2JfVR3kRVSJFc/GpQ2fSORi4pSHZR9orfM4UC9OVXIFFTA==",
"dev": true
},
"node_modules/@prisma/engines": {
- "version": "5.10.0-dev.1",
- "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.10.0-dev.1.tgz",
- "integrity": "sha512-zIu9K3K0CXAiqWJ63y6HTRKkgh8qylOaMXg6QvlRjPArm1nByHM9Qv5VOPyvIy5QYng8zPUIMi0AhPdtBWLe9g==",
+ "version": "5.9.1",
+ "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.9.1.tgz",
+ "integrity": "sha512-gkdXmjxQ5jktxWNdDA5aZZ6R8rH74JkoKq6LD5mACSvxd2vbqWeWIOV0Py5wFC8vofOYShbt6XUeCIUmrOzOnQ==",
"dev": true,
"hasInstallScript": true,
"dependencies": {
- "@prisma/debug": "5.10.0-dev.1",
+ "@prisma/debug": "5.9.1",
"@prisma/engines-version": "5.9.0-32.23fdc5965b1e05fc54e5f26ed3de66776b93de64",
- "@prisma/fetch-engine": "5.10.0-dev.1",
- "@prisma/get-platform": "5.10.0-dev.1"
+ "@prisma/fetch-engine": "5.9.1",
+ "@prisma/get-platform": "5.9.1"
}
},
"node_modules/@prisma/engines-version": {
@@ -2044,23 +2044,23 @@
"dev": true
},
"node_modules/@prisma/fetch-engine": {
- "version": "5.10.0-dev.1",
- "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.10.0-dev.1.tgz",
- "integrity": "sha512-4sRlPxxnSHMACgLYv8Fa9yvOPQfIws0QpjpOyIe6i87O8J2JOkcptNao4VVjQt5CVPQQllAnuRkBRBQq78kTcQ==",
+ "version": "5.9.1",
+ "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.9.1.tgz",
+ "integrity": "sha512-l0goQOMcNVOJs1kAcwqpKq3ylvkD9F04Ioe1oJoCqmz05mw22bNAKKGWuDd3zTUoUZr97va0c/UfLNru+PDmNA==",
"dev": true,
"dependencies": {
- "@prisma/debug": "5.10.0-dev.1",
+ "@prisma/debug": "5.9.1",
"@prisma/engines-version": "5.9.0-32.23fdc5965b1e05fc54e5f26ed3de66776b93de64",
- "@prisma/get-platform": "5.10.0-dev.1"
+ "@prisma/get-platform": "5.9.1"
}
},
"node_modules/@prisma/get-platform": {
- "version": "5.10.0-dev.1",
- "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.10.0-dev.1.tgz",
- "integrity": "sha512-X1oHa6Tssm12iQUM3UOglmZYiZU9DsS0rCVb3YpViRweIWDvQM2G/9Zdc/y1lns2+gUAWKMZQ4LEYPSs/uA40w==",
+ "version": "5.9.1",
+ "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.9.1.tgz",
+ "integrity": "sha512-6OQsNxTyhvG+T2Ksr8FPFpuPeL4r9u0JF0OZHUBI/Uy9SS43sPyAIutt4ZEAyqWQt104ERh70EZedkHZKsnNbg==",
"dev": true,
"dependencies": {
- "@prisma/debug": "5.10.0-dev.1"
+ "@prisma/debug": "5.9.1"
}
},
"node_modules/@radix-ui/primitive": {
@@ -3037,17 +3037,17 @@
}
},
"node_modules/@remix-run/css-bundle": {
- "version": "2.5.1",
- "resolved": "https://registry.npmjs.org/@remix-run/css-bundle/-/css-bundle-2.5.1.tgz",
- "integrity": "sha512-QPeNvgD7fj4NmXB9CuGM5Mp0ZtM43dMeda8Ik3AUoQOMgMWb0d4jK4Cye6eoTGwJOron6XISKh0mq8MorucWEQ==",
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@remix-run/css-bundle/-/css-bundle-2.6.0.tgz",
+ "integrity": "sha512-c3I1FVsWeBoA3c92Fwa1sufxAlosovfE2V7hwjc9HeQHA3DAHe18RXfgU6my/IvpItkIvaEgQPuoWEA6Dh8VDQ==",
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/@remix-run/dev": {
- "version": "2.5.1",
- "resolved": "https://registry.npmjs.org/@remix-run/dev/-/dev-2.5.1.tgz",
- "integrity": "sha512-IrYhWANubH+WM62Wz55n8NWT5kBqfbyytXDFlP0VoZLrr1IpJf2GtaT4IA+CODMaNoeXeMACOD5Tw5/Y2bO5lA==",
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@remix-run/dev/-/dev-2.6.0.tgz",
+ "integrity": "sha512-wf5DoKxBwz3/84FNyFM6NKvQIOEv+Ukwj9DjXrDs6YLI6oSqw2XsJCxWN4lAbOxXuK37pBt1WAE8LzEMuyowsw==",
"dev": true,
"dependencies": {
"@babel/core": "^7.21.8",
@@ -3060,9 +3060,9 @@
"@babel/types": "^7.22.5",
"@mdx-js/mdx": "^2.3.0",
"@npmcli/package-json": "^4.0.1",
- "@remix-run/node": "2.5.1",
- "@remix-run/router": "1.14.2",
- "@remix-run/server-runtime": "2.5.1",
+ "@remix-run/node": "2.6.0",
+ "@remix-run/router": "1.15.0",
+ "@remix-run/server-runtime": "2.6.0",
"@types/mdx": "^2.0.5",
"@vanilla-extract/integration": "^6.2.0",
"arg": "^5.0.1",
@@ -3111,9 +3111,10 @@
"node": ">=18.0.0"
},
"peerDependencies": {
- "@remix-run/serve": "^2.5.1",
+ "@remix-run/serve": "^2.6.0",
"typescript": "^5.1.0",
- "vite": "^5.0.0"
+ "vite": "^5.0.0",
+ "wrangler": "^3.24.0"
},
"peerDependenciesMeta": {
"@remix-run/serve": {
@@ -3124,6 +3125,9 @@
},
"vite": {
"optional": true
+ },
+ "wrangler": {
+ "optional": true
}
}
},
@@ -3714,9 +3718,9 @@
}
},
"node_modules/@remix-run/eslint-config": {
- "version": "2.5.1",
- "resolved": "https://registry.npmjs.org/@remix-run/eslint-config/-/eslint-config-2.5.1.tgz",
- "integrity": "sha512-PpLj0QSd2NZ12KdTA2QYPd/FK3Szu9Np7kTmx26VxDZJTzQYSgGb5i2O9uby+j2sD68zR/+EAYaIcOlq66ekJw==",
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@remix-run/eslint-config/-/eslint-config-2.6.0.tgz",
+ "integrity": "sha512-WIYyCl8qHNDyZy05ggzl/x3wbnLtmHWOaeSqvtshYbvBsKpyLT0xVQNWyj0XEzk6hWWk+93b0yQ5ihumjM4Y1Q==",
"dev": true,
"dependencies": {
"@babel/core": "^7.21.8",
@@ -3751,11 +3755,11 @@
}
},
"node_modules/@remix-run/express": {
- "version": "2.5.1",
- "resolved": "https://registry.npmjs.org/@remix-run/express/-/express-2.5.1.tgz",
- "integrity": "sha512-ISaf2hzHxDTS1hNsOovRoSfIQC29m4ogzXvBC6xp2BuJj0K8R0yQ4RFD4+qUFEUnS2n6MyWyjFQRhOC6PhQhRw==",
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@remix-run/express/-/express-2.6.0.tgz",
+ "integrity": "sha512-sAb0eoMwqP4yhDCnT5H6Db0svfzBuRbuPuPSbQCtuLRWkEGmIhWN7vKA0IqaxsUA09qKwQQiKQdupra55KfCyA==",
"dependencies": {
- "@remix-run/node": "2.5.1"
+ "@remix-run/node": "2.6.0"
},
"engines": {
"node": ">=18.0.0"
@@ -3771,11 +3775,11 @@
}
},
"node_modules/@remix-run/node": {
- "version": "2.5.1",
- "resolved": "https://registry.npmjs.org/@remix-run/node/-/node-2.5.1.tgz",
- "integrity": "sha512-UI442xzHAiokmsfrYOabMQB024+IizmRhZBGcNa42QjJWsNqogy1bNwYhzEpB6oQEB1wF3vwOKK1AD1/iYA/9A==",
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@remix-run/node/-/node-2.6.0.tgz",
+ "integrity": "sha512-bWemy3g258Kdqi+4OxIEZ7QS64T96jNK6a7NdlPXGJZqeLpxM5NmlCl/slSdx52oTi9r5Xoz1Tm4uR37nD1/Xw==",
"dependencies": {
- "@remix-run/server-runtime": "2.5.1",
+ "@remix-run/server-runtime": "2.6.0",
"@remix-run/web-fetch": "^4.4.2",
"@remix-run/web-file": "^3.1.0",
"@remix-run/web-stream": "^1.1.0",
@@ -3797,14 +3801,14 @@
}
},
"node_modules/@remix-run/react": {
- "version": "2.5.1",
- "resolved": "https://registry.npmjs.org/@remix-run/react/-/react-2.5.1.tgz",
- "integrity": "sha512-MNXHLj4Iu9Iyi+3uY61JZJ1Rtx2nM/z11j9AtwQdEADkh1/t9GruhtT/8VLplToOl0qWZKItboWScKf6uRQsrw==",
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@remix-run/react/-/react-2.6.0.tgz",
+ "integrity": "sha512-m/Ph6bryny7wrmrQyXQMvIiW+cBLrU/MepcLGFPvTVVwvfeiGBgXRiYZJ6yPNsfrmHFaS83d+Ja/Mx4N4zUWcg==",
"dependencies": {
- "@remix-run/router": "1.14.2",
- "@remix-run/server-runtime": "2.5.1",
- "react-router": "6.21.3",
- "react-router-dom": "6.21.3"
+ "@remix-run/router": "1.15.0",
+ "@remix-run/server-runtime": "2.6.0",
+ "react-router": "6.22.0",
+ "react-router-dom": "6.22.0"
},
"engines": {
"node": ">=18.0.0"
@@ -3821,21 +3825,21 @@
}
},
"node_modules/@remix-run/router": {
- "version": "1.14.2",
- "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.14.2.tgz",
- "integrity": "sha512-ACXpdMM9hmKZww21yEqWwiLws/UPLhNKvimN8RrYSqPSvB3ov7sLvAcfvaxePeLvccTQKGdkDIhLYApZVDFuKg==",
+ "version": "1.15.0",
+ "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.0.tgz",
+ "integrity": "sha512-HOil5aFtme37dVQTB6M34G95kPM3MMuqSmIRVCC52eKV+Y/tGSqw9P3rWhlAx6A+mz+MoX+XxsGsNJbaI5qCgQ==",
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/@remix-run/serve": {
- "version": "2.5.1",
- "resolved": "https://registry.npmjs.org/@remix-run/serve/-/serve-2.5.1.tgz",
- "integrity": "sha512-r1IWfirwkLrxADd8uFUIpLR1wMU8VeRI4ED4SpbhrKwqODLrYtv5irzjei+r/w0y0Oob8DMHnYxg03UY4T7ejg==",
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@remix-run/serve/-/serve-2.6.0.tgz",
+ "integrity": "sha512-OIvGWaruFLCMLpemovitE8WnxRD/4TBPDTsgC/pSxcjDfuXv3nZk0nhAcmfklPSnxBCCct50cbtEN1xcrPqeyw==",
"dev": true,
"dependencies": {
- "@remix-run/express": "2.5.1",
- "@remix-run/node": "2.5.1",
+ "@remix-run/express": "2.6.0",
+ "@remix-run/node": "2.6.0",
"chokidar": "^3.5.3",
"compression": "^1.7.4",
"express": "^4.17.1",
@@ -3863,11 +3867,11 @@
}
},
"node_modules/@remix-run/server-runtime": {
- "version": "2.5.1",
- "resolved": "https://registry.npmjs.org/@remix-run/server-runtime/-/server-runtime-2.5.1.tgz",
- "integrity": "sha512-bP31jrVbYTJ2eP5sxZfDgT1YyXzDlzsfMxGYVzpaoLCYDJAekq1QpHLLXKGOXhmyb46O9rdhlQKfwD6WpAxr3A==",
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@remix-run/server-runtime/-/server-runtime-2.6.0.tgz",
+ "integrity": "sha512-qFXDl4pK55njBLuvyRn5AkI/hu8fEU3t1XFKv0Syivx0nmUVpWMW25Uzi1pkX/chF1VIxCVrZ8KuQ1rcrKj+DQ==",
"dependencies": {
- "@remix-run/router": "1.14.2",
+ "@remix-run/router": "1.15.0",
"@types/cookie": "^0.6.0",
"@web3-storage/multipart-parser": "^1.0.0",
"cookie": "^0.6.0",
@@ -3887,15 +3891,15 @@
}
},
"node_modules/@remix-run/testing": {
- "version": "2.5.1",
- "resolved": "https://registry.npmjs.org/@remix-run/testing/-/testing-2.5.1.tgz",
- "integrity": "sha512-No7e7/Kvu7NoXrXEsSKVEP9YFLeUpkGME54f3R4jAd2mvLySY5f87iFVub3ZhdgqLQOxLuJfLPrdaz1Ml2hSDg==",
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@remix-run/testing/-/testing-2.6.0.tgz",
+ "integrity": "sha512-hjIQxSke6ohccJrKKlB9j36W7pXesTR7+nkq68+A+NAZWt6wYCB+iSOKveqmtsmGiXnSOfFMhZcNNrMJjyRrLw==",
"dev": true,
"dependencies": {
- "@remix-run/node": "2.5.1",
- "@remix-run/react": "2.5.1",
- "@remix-run/router": "1.14.2",
- "react-router-dom": "6.21.3"
+ "@remix-run/node": "2.6.0",
+ "@remix-run/react": "2.6.0",
+ "@remix-run/router": "1.15.0",
+ "react-router-dom": "6.22.0"
},
"engines": {
"node": ">=18.0.0"
@@ -5308,9 +5312,9 @@
"dev": true
},
"node_modules/@testing-library/react": {
- "version": "14.2.0",
- "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-14.2.0.tgz",
- "integrity": "sha512-7uBnPHyOG6nDGCzv8SLeJbSa33ZoYw7swYpSLIgJvBALdq7l9zPNk33om4USrxy1lKTxXaVfufzLmq83WNfWIw==",
+ "version": "14.2.1",
+ "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-14.2.1.tgz",
+ "integrity": "sha512-sGdjws32ai5TLerhvzThYFbpnF9XtL65Cjf+gB0Dhr29BGqK+mAeN7SURSdu+eqgET4ANcWoC7FQpkaiGvBr+A==",
"dev": true,
"dependencies": {
"@babel/runtime": "^7.12.5",
@@ -5610,9 +5614,9 @@
"dev": true
},
"node_modules/@types/node": {
- "version": "20.11.14",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.14.tgz",
- "integrity": "sha512-w3yWCcwULefjP9DmDDsgUskrMoOy5Z8MiwKHr1FvqGPtx7CvJzQvxD7eKpxNtklQxLruxSXWddyeRtyud0RcXQ==",
+ "version": "20.11.16",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.16.tgz",
+ "integrity": "sha512-gKb0enTmRCzXSSUJDq6/sPcqrfCv2mkkG6Jt/clpn5eiCbKTY+SgZUxo+p8ZKMof5dCp9vHQUAB7wOUTod22wQ==",
"dev": true,
"dependencies": {
"undici-types": "~5.26.4"
@@ -5646,9 +5650,9 @@
"dev": true
},
"node_modules/@types/react": {
- "version": "18.2.50",
- "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.50.tgz",
- "integrity": "sha512-y0XIDJkqp9HynS1VBktZG9mUziHTK5WZTAFDP/UfzSq+poV1drUKsr4VkjMyHTbqMz26BwgLZVYdx/EgPm7EkQ==",
+ "version": "18.2.51",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.51.tgz",
+ "integrity": "sha512-XeoMaU4CzyjdRr3c4IQQtiH7Rpo18V07rYZUucEZQwOUEtGgTXv7e6igQiQ+xnV6MbMe1qjEmKdgMNnfppnXfg==",
"dev": true,
"dependencies": {
"@types/prop-types": "*",
@@ -15141,12 +15145,12 @@
}
},
"node_modules/playwright": {
- "version": "1.41.1",
- "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.41.1.tgz",
- "integrity": "sha512-gdZAWG97oUnbBdRL3GuBvX3nDDmUOuqzV/D24dytqlKt+eI5KbwusluZRGljx1YoJKZ2NRPaeWiFTeGZO7SosQ==",
+ "version": "1.41.2",
+ "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.41.2.tgz",
+ "integrity": "sha512-v0bOa6H2GJChDL8pAeLa/LZC4feoAMbSQm1/jF/ySsWWoaNItvrMP7GEkvEEFyCTUYKMxjQKaTSg5up7nR6/8A==",
"dev": true,
"dependencies": {
- "playwright-core": "1.41.1"
+ "playwright-core": "1.41.2"
},
"bin": {
"playwright": "cli.js"
@@ -15159,9 +15163,9 @@
}
},
"node_modules/playwright-core": {
- "version": "1.41.1",
- "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.41.1.tgz",
- "integrity": "sha512-/KPO5DzXSMlxSX77wy+HihKGOunh3hqndhqeo/nMxfigiKzogn8kfL0ZBDu0L1RKgan5XHCPmn6zXd2NUJgjhg==",
+ "version": "1.41.2",
+ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.41.2.tgz",
+ "integrity": "sha512-VaTvwCA4Y8kxEe+kfm2+uUUw5Lubf38RxF7FpBxLPmGe5sdNkSg5e3ChEigaGrX7qdqT3pt2m/98LiyvU2x6CA==",
"dev": true,
"bin": {
"playwright-core": "cli.js"
@@ -15599,13 +15603,13 @@
}
},
"node_modules/prisma": {
- "version": "5.10.0-dev.1",
- "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.10.0-dev.1.tgz",
- "integrity": "sha512-11ppGQks5MPTAqYQjYXS5BHdvrPNP62FjqmM6Y6omP4zdcTKj11RJ+wPWwWE71OK/doY4+YnnbIaXDtUSHDAMA==",
+ "version": "5.9.1",
+ "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.9.1.tgz",
+ "integrity": "sha512-Hy/8KJZz0ELtkw4FnG9MS9rNWlXcJhf98Z2QMqi0QiVMoS8PzsBkpla0/Y5hTlob8F3HeECYphBjqmBxrluUrQ==",
"dev": true,
"hasInstallScript": true,
"dependencies": {
- "@prisma/engines": "5.10.0-dev.1"
+ "@prisma/engines": "5.9.1"
},
"bin": {
"prisma": "build/index.js"
@@ -16132,11 +16136,11 @@
}
},
"node_modules/react-router": {
- "version": "6.21.3",
- "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.21.3.tgz",
- "integrity": "sha512-a0H638ZXULv1OdkmiK6s6itNhoy33ywxmUFT/xtSoVyf9VnC7n7+VT4LjVzdIHSaF5TIh9ylUgxMXksHTgGrKg==",
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.22.0.tgz",
+ "integrity": "sha512-q2yemJeg6gw/YixRlRnVx6IRJWZD6fonnfZhN1JIOhV2iJCPeRNSH3V1ISwHf+JWcESzLC3BOLD1T07tmO5dmg==",
"dependencies": {
- "@remix-run/router": "1.14.2"
+ "@remix-run/router": "1.15.0"
},
"engines": {
"node": ">=14.0.0"
@@ -16146,12 +16150,12 @@
}
},
"node_modules/react-router-dom": {
- "version": "6.21.3",
- "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.21.3.tgz",
- "integrity": "sha512-kNzubk7n4YHSrErzjLK72j0B5i969GsuCGazRl3G6j1zqZBLjuSlYBdVdkDOgzGdPIffUOc9nmgiadTEVoq91g==",
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.22.0.tgz",
+ "integrity": "sha512-z2w+M4tH5wlcLmH3BMMOMdrtrJ9T3oJJNsAlBJbwk+8Syxd5WFJ7J5dxMEW0/GEXD1BBis4uXRrNIz3mORr0ag==",
"dependencies": {
- "@remix-run/router": "1.14.2",
- "react-router": "6.21.3"
+ "@remix-run/router": "1.15.0",
+ "react-router": "6.22.0"
},
"engines": {
"node": ">=14.0.0"
diff --git a/package.json b/package.json
index 186588c..e6a1318 100644
--- a/package.json
+++ b/package.json
@@ -47,7 +47,7 @@
"@epic-web/totp": "^1.1.1",
"@nasa-gcn/remix-seo": "^2.0.0",
"@paralleldrive/cuid2": "^2.2.2",
- "@prisma/client": "^5.10.0-dev.1",
+ "@prisma/client": "^5.9.1",
"@radix-ui/react-checkbox": "^1.0.4",
"@radix-ui/react-dialog": "^1.0.5",
"@radix-ui/react-dropdown-menu": "^2.0.6",
@@ -56,11 +56,11 @@
"@radix-ui/react-toast": "^1.1.5",
"@radix-ui/react-tooltip": "^1.0.7",
"@react-email/components": "0.0.14",
- "@remix-run/css-bundle": "^2.5.1",
- "@remix-run/express": "^2.5.1",
- "@remix-run/node": "^2.5.1",
- "@remix-run/react": "^2.5.1",
- "@remix-run/server-runtime": "^2.5.1",
+ "@remix-run/css-bundle": "^2.6.0",
+ "@remix-run/express": "^2.6.0",
+ "@remix-run/node": "^2.6.0",
+ "@remix-run/react": "^2.6.0",
+ "@remix-run/server-runtime": "^2.6.0",
"@sentry/profiling-node": "^1.3.5",
"@sentry/remix": "^7.99.0",
"address": "^2.0.1",
@@ -108,14 +108,14 @@
},
"devDependencies": {
"@faker-js/faker": "^8.4.0",
- "@playwright/test": "^1.41.1",
- "@remix-run/dev": "^2.5.1",
- "@remix-run/eslint-config": "^2.5.1",
- "@remix-run/serve": "^2.5.1",
- "@remix-run/testing": "^2.5.1",
+ "@playwright/test": "^1.41.2",
+ "@remix-run/dev": "^2.6.0",
+ "@remix-run/eslint-config": "^2.6.0",
+ "@remix-run/serve": "^2.6.0",
+ "@remix-run/testing": "^2.6.0",
"@sly-cli/sly": "^1.8.0",
"@testing-library/jest-dom": "^6.4.1",
- "@testing-library/react": "^14.2.0",
+ "@testing-library/react": "^14.2.1",
"@testing-library/user-event": "^14.5.2",
"@total-typescript/ts-reset": "^0.5.1",
"@types/bcryptjs": "^2.4.6",
@@ -127,9 +127,9 @@
"@types/fs-extra": "^11.0.4",
"@types/glob": "^8.1.0",
"@types/morgan": "^1.9.9",
- "@types/node": "^20.11.14",
+ "@types/node": "^20.11.16",
"@types/qrcode": "^1.5.5",
- "@types/react": "^18.2.50",
+ "@types/react": "^18.2.51",
"@types/react-dom": "^18.2.18",
"@types/set-cookie-parser": "^2.4.7",
"@types/source-map-support": "^0.5.10",
@@ -148,7 +148,7 @@
"prettier": "^3.2.4",
"prettier-plugin-sql": "^0.18.0",
"prettier-plugin-tailwindcss": "^0.5.11",
- "prisma": "^5.10.0-dev.1",
+ "prisma": "^5.9.1",
"remix-flat-routes": "^0.6.4",
"rimraf": "^5.0.5",
"tsx": "^4.7.0",
diff --git a/prisma/schema.prisma b/prisma/schema.prisma
index d05cdb9..efdcd64 100644
--- a/prisma/schema.prisma
+++ b/prisma/schema.prisma
@@ -19,15 +19,16 @@ model User {
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
- image UserImage?
- password Password?
+ password Password?
+ image UserImage?
+ platformStatus PlatformStatus? @relation(fields: [platformStatusId], references: [id])
+ platformStatusId Int?
+
notes Note[]
roles Role[]
sessions Session[]
userCompanies UserCompany[]
connections Connection[]
- transactions Transaction[]
- invoices Invoice[]
}
model Note {
@@ -172,93 +173,185 @@ model Connection {
@@unique([providerName, providerId])
}
+model PlatformStatus {
+ id Int @id @default(autoincrement())
+ key String @unique
+ label String?
+ color String?
+
+ createdAt DateTime @default(now())
+ updatedAt DateTime? @updatedAt
+
+ companies Company[]
+ users User[]
+}
+
+model TransactionStatus {
+ id Int @id @default(autoincrement())
+ key String @unique
+ label String?
+ color String?
+
+ createdAt DateTime @default(now())
+ updatedAt DateTime? @updatedAt
+
+ // ! Maybe remove transactions from here? I would hardly ever use them to query
+ transactions Transaction[]
+ saleInvoices SaleInvoice[]
+ purchaseBills PurchaseBill[]
+}
+
// * Account specific models
// * This is for a simple personal finance app
// Company model represents a business entity or organization that the accounting system will handle.
model Company {
- id String @id @default(cuid())
- name String // Name of the company or business entity.
+ id String @id @default(cuid())
+ name String // Name of the company or business entity.
+
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+
+ platformStatus PlatformStatus? @relation(fields: [platformStatusId], references: [id])
+ platformStatusId Int?
+
users UserCompany[] // Users associated with the company.
accounts Account[] // Financial accounts belonging to the company.
- invoices Invoice[] // Invoices generated by the company.
+ saleInvoices SaleInvoice[] // Invoices generated by the company.
transactions Transaction[] // Financial transactions recorded for the company.
- createdAt DateTime @default(now())
- updatedAt DateTime @updatedAt
+ PurchaseBill PurchaseBill[] // Bills received by the company.
}
// UserCompany is a join table that allows users to be associated with multiple companies.
// It serves as a many-to-many relationship between User and Company models.
model UserCompany {
- id Int @id @default(autoincrement())
+ id Int @id @default(autoincrement())
+ isOwner Boolean @default(false)
+
user User @relation(fields: [userId], references: [id])
userId String
company Company @relation(fields: [companyId], references: [id])
companyId String
- isOwner Boolean @default(false)
Role Role[]
+
+ transactions Transaction[]
+ saleInvoices SaleInvoice[]
+ purchaseBills PurchaseBill[]
}
// Account model represents financial ledgers which are used to record transactions
// and keep track of the financial status of various aspects of the company such as assets, liabilities, revenue, etc.
model Account {
- id Int @id @default(autoincrement())
- company Company @relation(fields: [companyId], references: [id])
- companyId String
- name String // Name of the financial ledger/account.
- balance Float // Current balance of the account.
- type String // Type of the account, e.g., revenue, expense.
+ id Int @id @default(autoincrement())
+ name String // Name of the financial ledger/account.
+ balance Float // Current balance of the account.
+ type String // Type of the account, e.g., revenue, expense.
+
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+
+ company Company @relation(fields: [companyId], references: [id])
+ companyId String
+
transactions Transaction[] // Transactions associated with this account.
- createdAt DateTime @default(now())
- updatedAt DateTime @updatedAt
+ PurchaseBill PurchaseBill[] // Bills associated with this account.
+ SaleInvoice SaleInvoice[] // Invoices associated with this account.
}
// Transaction model records all the financial activities which affect accounts, defined by a change in balance.
model Transaction {
id Int @id @default(autoincrement())
- company Company @relation(fields: [companyId], references: [id])
- companyId String
date DateTime @default(now())
- account Account @relation(fields: [accountId], references: [id])
- accountId Int
description String // Describes the purpose of the transaction.
amount Float // The monetary value of the transaction.
- type String // Type can include 'sale', 'purchase', etc.
+ type String? // Type can include 'sale', 'purchase', etc.
category String // Categorizes the transaction for accounting purposes.
- createdAt DateTime @default(now())
- updatedAt DateTime @updatedAt
- User User? @relation(fields: [userId], references: [id])
- userId String?
+
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+
+ company Company @relation(fields: [companyId], references: [id])
+ companyId String
+ account Account @relation(fields: [accountId], references: [id])
+ accountId Int
+ issuedBy UserCompany? @relation(fields: [issuedById], references: [id])
+ issuedById Int?
+ transactionStatus TransactionStatus? @relation(fields: [transactionStatusId], references: [id])
+ transactionStatusId Int?
}
// Invoice model represents bills to be sent to clients or received from suppliers,
// which can include one or more payable items, and their total has an impact on the company's finances.
-model Invoice {
- id Int @id @default(autoincrement())
- company Company @relation(fields: [companyId], references: [id])
- companyId String
- dateIssued DateTime @default(now())
+model SaleInvoice {
+ id Int @id @default(autoincrement())
+ dateIssued DateTime @default(now())
dueDate DateTime // The date by which the invoice should be paid.
- items InvoiceItem[] // Line items detailing individual charges on the invoice.
totalAmount Float // Total monetary value to be paid / received for the invoice.
- status String // Status could be 'pending', 'paid', 'overdue', etc.
- createdAt DateTime @default(now())
- updatedAt DateTime @updatedAt
- User User? @relation(fields: [userId], references: [id])
- userId String?
+
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+
+ company Company @relation(fields: [companyId], references: [id])
+ companyId String
+ issuedTo Account @relation(fields: [issuedToId], references: [id])
+ issuedToId Int
+ issuedBy UserCompany? @relation(fields: [issuedById], references: [id])
+ issuedById Int?
+ transactionStatus TransactionStatus? @relation(fields: [transactionStatusId], references: [id])
+ transactionStatusId Int?
+
+ items InvoiceItem[] // Line items detailing individual charges on the invoice.
}
// InvoiceItem model holds the details of each item or service listed in an invoice.
// Each item has a price and quantity which contribute to the invoice's total.
model InvoiceItem {
- id Int @id @default(autoincrement())
- invoice Invoice @relation(fields: [invoiceId], references: [id])
+ id Int @id @default(autoincrement())
+ invoice SaleInvoice @relation(fields: [invoiceId], references: [id])
invoiceId Int
- description String // Details of what the item or service is.
+ description String? // Details of what the item or service is.
quantity Int // Quantity of the item or service provided.
price Float // Price per unit of the item or service.
- total Float @default(0) // Total price for the line item.
- createdAt DateTime @default(now())
- updatedAt DateTime @updatedAt
+ total Float @default(0) // Total price for the line item.
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+}
+
+// PurchaseBill model for purchase transactions from vendors
+model PurchaseBill {
+ id String @id @default(cuid())
+ companyId String
+ company Company @relation(fields: [companyId], references: [id])
+ dateIssued DateTime @default(now())
+ dueDate DateTime // Due date for payment.
+ totalAmount Float // Total amount of the bill.
+ vendor String? // Vendor identifier or name.
+
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+
+ issuedTo Account @relation(fields: [issuedToId], references: [id]) // Account to which the bill is issued.
+ issuedToId Int
+
+ // Optional: Relate to a user who manages the bill
+ issuedBy UserCompany? @relation(fields: [issuedById], references: [id])
+ issuedById Int?
+ transactionStatus TransactionStatus? @relation(fields: [transactionStatusId], references: [id])
+ transactionStatusId Int?
+
+ purchaseBillItems PurchaseBillItem[] // Individual items on the bill.
+}
+
+// PurchaseBillItem model for line items on a purchase bill
+model PurchaseBillItem {
+ id Int @id @default(autoincrement())
+ purchaseBill PurchaseBill @relation(fields: [purchaseBillId], references: [id])
+ purchaseBillId String
+ description String? // Description of the item or service.
+ quantity Int // Quantity of the item.
+ price Float // Unit price of the item.
+ total Float // Line item total (quantity * price).
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
}