lblt 1 月之前
父節點
當前提交
f936f12447
共有 41 個文件被更改,包括 3731 次插入420 次删除
  1. 314 1
      package-lock.json
  2. 7 6
      package.json
  3. 122 35
      src/App.tsx
  4. 249 26
      src/authProvider.ts
  5. 117 6
      src/components/header/index.tsx
  6. 163 0
      src/pages/apps/create.tsx
  7. 2 2
      src/pages/apps/index.ts
  8. 74 0
      src/pages/apps/list.tsx
  9. 171 0
      src/pages/apps/show.tsx
  10. 0 71
      src/pages/blog-posts/create.tsx
  11. 0 78
      src/pages/blog-posts/edit.tsx
  12. 0 73
      src/pages/blog-posts/list.tsx
  13. 0 41
      src/pages/blog-posts/show.tsx
  14. 0 24
      src/pages/categories/create.tsx
  15. 0 24
      src/pages/categories/edit.tsx
  16. 0 21
      src/pages/categories/show.tsx
  17. 114 0
      src/pages/clients/create.tsx
  18. 2 0
      src/pages/clients/index.ts
  19. 63 0
      src/pages/clients/list.tsx
  20. 1 0
      src/pages/dashboard/index.ts
  21. 314 0
      src/pages/dashboard/overview.tsx
  22. 80 0
      src/pages/deployments/create.tsx
  23. 1 2
      src/pages/deployments/index.ts
  24. 22 5
      src/pages/deployments/list.tsx
  25. 93 0
      src/pages/deployments/show.tsx
  26. 58 1
      src/pages/forgotPassword/index.tsx
  27. 38 1
      src/pages/login/index.tsx
  28. 180 0
      src/pages/monitoring/dashboard.tsx
  29. 1 0
      src/pages/monitoring/index.ts
  30. 128 3
      src/pages/register/index.tsx
  31. 1 0
      src/pages/support/index.ts
  32. 173 0
      src/pages/support/tickets.tsx
  33. 535 0
      src/pages/templates/create.tsx
  34. 3 0
      src/pages/templates/index.ts
  35. 88 0
      src/pages/templates/list.tsx
  36. 287 0
      src/pages/templates/show.tsx
  37. 50 0
      src/types/app.ts
  38. 66 0
      src/types/client.ts
  39. 72 0
      src/types/deployment.ts
  40. 83 0
      src/types/template.ts
  41. 59 0
      src/types/user.ts

+ 314 - 1
package-lock.json

@@ -20,7 +20,8 @@
         "antd": "^5.17.0",
         "react": "^18.0.0",
         "react-dom": "^18.0.0",
-        "react-router": "^7.0.2"
+        "react-router": "^7.0.2",
+        "recharts": "^2.15.3"
       },
       "devDependencies": {
         "@types/node": "^18.16.2",
@@ -2245,6 +2246,69 @@
         "@babel/types": "^7.20.7"
       }
     },
+    "node_modules/@types/d3-array": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz",
+      "integrity": "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==",
+      "license": "MIT"
+    },
+    "node_modules/@types/d3-color": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz",
+      "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==",
+      "license": "MIT"
+    },
+    "node_modules/@types/d3-ease": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz",
+      "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==",
+      "license": "MIT"
+    },
+    "node_modules/@types/d3-interpolate": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz",
+      "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==",
+      "license": "MIT",
+      "dependencies": {
+        "@types/d3-color": "*"
+      }
+    },
+    "node_modules/@types/d3-path": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz",
+      "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==",
+      "license": "MIT"
+    },
+    "node_modules/@types/d3-scale": {
+      "version": "4.0.9",
+      "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz",
+      "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==",
+      "license": "MIT",
+      "dependencies": {
+        "@types/d3-time": "*"
+      }
+    },
+    "node_modules/@types/d3-shape": {
+      "version": "3.1.7",
+      "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.7.tgz",
+      "integrity": "sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg==",
+      "license": "MIT",
+      "dependencies": {
+        "@types/d3-path": "*"
+      }
+    },
+    "node_modules/@types/d3-time": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz",
+      "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==",
+      "license": "MIT"
+    },
+    "node_modules/@types/d3-timer": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz",
+      "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==",
+      "license": "MIT"
+    },
     "node_modules/@types/debug": {
       "version": "4.1.12",
       "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz",
@@ -4048,6 +4112,15 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/clsx": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
+      "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6"
+      }
+    },
     "node_modules/color-convert": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
@@ -4237,6 +4310,127 @@
       "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
       "license": "MIT"
     },
+    "node_modules/d3-array": {
+      "version": "3.2.4",
+      "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz",
+      "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==",
+      "license": "ISC",
+      "dependencies": {
+        "internmap": "1 - 2"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/d3-color": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz",
+      "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==",
+      "license": "ISC",
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/d3-ease": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz",
+      "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==",
+      "license": "BSD-3-Clause",
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/d3-format": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz",
+      "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==",
+      "license": "ISC",
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/d3-interpolate": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz",
+      "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==",
+      "license": "ISC",
+      "dependencies": {
+        "d3-color": "1 - 3"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/d3-path": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz",
+      "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==",
+      "license": "ISC",
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/d3-scale": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz",
+      "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==",
+      "license": "ISC",
+      "dependencies": {
+        "d3-array": "2.10.0 - 3",
+        "d3-format": "1 - 3",
+        "d3-interpolate": "1.2.0 - 3",
+        "d3-time": "2.1.1 - 3",
+        "d3-time-format": "2 - 4"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/d3-shape": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz",
+      "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==",
+      "license": "ISC",
+      "dependencies": {
+        "d3-path": "^3.1.0"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/d3-time": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz",
+      "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==",
+      "license": "ISC",
+      "dependencies": {
+        "d3-array": "2 - 3"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/d3-time-format": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz",
+      "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==",
+      "license": "ISC",
+      "dependencies": {
+        "d3-time": "1 - 3"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/d3-timer": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz",
+      "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==",
+      "license": "ISC",
+      "engines": {
+        "node": ">=12"
+      }
+    },
     "node_modules/dayjs": {
       "version": "1.11.13",
       "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz",
@@ -4287,6 +4481,12 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
+    "node_modules/decimal.js-light": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz",
+      "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==",
+      "license": "MIT"
+    },
     "node_modules/decode-named-character-reference": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.1.0.tgz",
@@ -4427,6 +4627,16 @@
         "node": ">=6.0.0"
       }
     },
+    "node_modules/dom-helpers": {
+      "version": "5.2.1",
+      "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
+      "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/runtime": "^7.8.7",
+        "csstype": "^3.0.2"
+      }
+    },
     "node_modules/dom-serializer": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
@@ -6555,6 +6765,15 @@
         "node": ">=8"
       }
     },
+    "node_modules/internmap": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz",
+      "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==",
+      "license": "ISC",
+      "engines": {
+        "node": ">=12"
+      }
+    },
     "node_modules/ipaddr.js": {
       "version": "1.9.1",
       "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
@@ -10192,6 +10411,46 @@
         "node": ">=18"
       }
     },
+    "node_modules/react-smooth": {
+      "version": "4.0.4",
+      "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.4.tgz",
+      "integrity": "sha512-gnGKTpYwqL0Iii09gHobNolvX4Kiq4PKx6eWBCYYix+8cdw+cGo3do906l1NBPKkSWx1DghC1dlWG9L2uGd61Q==",
+      "license": "MIT",
+      "dependencies": {
+        "fast-equals": "^5.0.1",
+        "prop-types": "^15.8.1",
+        "react-transition-group": "^4.4.5"
+      },
+      "peerDependencies": {
+        "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
+        "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+      }
+    },
+    "node_modules/react-smooth/node_modules/fast-equals": {
+      "version": "5.2.2",
+      "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.2.2.tgz",
+      "integrity": "sha512-V7/RktU11J3I36Nwq2JnZEM7tNm17eBJz+u25qdxBZeCKiX6BkVSZQjwWIr+IobgnZy+ag73tTZgZi7tr0LrBw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/react-transition-group": {
+      "version": "4.4.5",
+      "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
+      "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==",
+      "license": "BSD-3-Clause",
+      "dependencies": {
+        "@babel/runtime": "^7.5.5",
+        "dom-helpers": "^5.0.1",
+        "loose-envify": "^1.4.0",
+        "prop-types": "^15.6.2"
+      },
+      "peerDependencies": {
+        "react": ">=16.6.0",
+        "react-dom": ">=16.6.0"
+      }
+    },
     "node_modules/react-virtual": {
       "version": "2.10.4",
       "resolved": "https://registry.npmjs.org/react-virtual/-/react-virtual-2.10.4.tgz",
@@ -10237,6 +10496,38 @@
         "node": ">= 4"
       }
     },
+    "node_modules/recharts": {
+      "version": "2.15.3",
+      "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.15.3.tgz",
+      "integrity": "sha512-EdOPzTwcFSuqtvkDoaM5ws/Km1+WTAO2eizL7rqiG0V2UVhTnz0m7J2i0CjVPUCdEkZImaWvXLbZDS2H5t6GFQ==",
+      "license": "MIT",
+      "dependencies": {
+        "clsx": "^2.0.0",
+        "eventemitter3": "^4.0.1",
+        "lodash": "^4.17.21",
+        "react-is": "^18.3.1",
+        "react-smooth": "^4.0.4",
+        "recharts-scale": "^0.4.4",
+        "tiny-invariant": "^1.3.1",
+        "victory-vendor": "^36.6.8"
+      },
+      "engines": {
+        "node": ">=14"
+      },
+      "peerDependencies": {
+        "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
+        "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+      }
+    },
+    "node_modules/recharts-scale": {
+      "version": "0.4.5",
+      "resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.5.tgz",
+      "integrity": "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==",
+      "license": "MIT",
+      "dependencies": {
+        "decimal.js-light": "^2.4.1"
+      }
+    },
     "node_modules/redeyed": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz",
@@ -12779,6 +13070,28 @@
         "url": "https://opencollective.com/unified"
       }
     },
+    "node_modules/victory-vendor": {
+      "version": "36.9.2",
+      "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.9.2.tgz",
+      "integrity": "sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==",
+      "license": "MIT AND ISC",
+      "dependencies": {
+        "@types/d3-array": "^3.0.3",
+        "@types/d3-ease": "^3.0.0",
+        "@types/d3-interpolate": "^3.0.1",
+        "@types/d3-scale": "^4.0.2",
+        "@types/d3-shape": "^3.1.0",
+        "@types/d3-time": "^3.0.0",
+        "@types/d3-timer": "^3.0.0",
+        "d3-array": "^3.1.6",
+        "d3-ease": "^3.0.1",
+        "d3-interpolate": "^3.0.1",
+        "d3-scale": "^4.0.2",
+        "d3-shape": "^3.1.0",
+        "d3-time": "^3.0.0",
+        "d3-timer": "^3.0.1"
+      }
+    },
     "node_modules/vite": {
       "version": "4.5.14",
       "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.14.tgz",

+ 7 - 6
package.json

@@ -4,19 +4,20 @@
   "private": true,
   "type": "module",
   "dependencies": {
+    "@ant-design/icons": "^5.5.1",
+    "@refinedev/antd": "^5.44.0",
     "@refinedev/cli": "^2.16.21",
     "@refinedev/core": "^4.47.1",
     "@refinedev/devtools": "^1.1.32",
     "@refinedev/kbar": "^1.3.6",
+    "@refinedev/react-router": "^1.0.0",
+    "@refinedev/simple-rest": "^5.0.1",
+    "@uiw/react-md-editor": "^3.19.5",
+    "antd": "^5.17.0",
     "react": "^18.0.0",
     "react-dom": "^18.0.0",
     "react-router": "^7.0.2",
-    "@refinedev/simple-rest": "^5.0.1",
-    "@refinedev/antd": "^5.44.0",
-    "antd": "^5.17.0",
-    "@ant-design/icons": "^5.5.1",
-    "@uiw/react-md-editor": "^3.19.5",
-    "@refinedev/react-router": "^1.0.0"
+    "recharts": "^2.15.3"
   },
   "devDependencies": {
     "@types/node": "^18.16.2",

+ 122 - 35
src/App.tsx

@@ -1,4 +1,4 @@
-import { Authenticated, GitHubBanner, Refine } from "@refinedev/core";
+import { Authenticated, Refine } from "@refinedev/core";
 import { DevtoolsPanel, DevtoolsProvider } from "@refinedev/devtools";
 import { RefineKbar, RefineKbarProvider } from "@refinedev/kbar";
 
@@ -22,54 +22,119 @@ import { BrowserRouter, Outlet, Route, Routes } from "react-router";
 import { authProvider } from "./authProvider";
 import { Header } from "./components/header";
 import { ColorModeContextProvider } from "./contexts/color-mode";
+
+// Import our custom pages
+import {
+  DeploymentList,
+  DeploymentCreate,
+  DeploymentShow,
+} from "./pages/deployments";
+import {
+  TemplateList,
+  TemplateCreate,
+  TemplateShow,
+} from "./pages/templates";
+import {
+  AppList,
+  AppCreate,
+  AppShow,
+} from "./pages/apps";
+import {
+  ClientCreate,
+  ClientList,
+} from "./pages/clients";
 import {
-  BlogPostCreate,
-  BlogPostEdit,
-  BlogPostList,
-  BlogPostShow,
-} from "./pages/blog-posts";
+  MonitoringDashboard,
+} from "./pages/monitoring";
 import {
-  CategoryCreate,
-  CategoryEdit,
-  CategoryList,
-  CategoryShow,
-} from "./pages/categories";
+  SupportTickets,
+} from "./pages/support";
+import {
+  DashboardOverview,
+} from "./pages/dashboard";
+
 import { ForgotPassword } from "./pages/forgotPassword";
 import { Login } from "./pages/login";
 import { Register } from "./pages/register";
+import { DashboardOutlined, AppstoreOutlined } from "@ant-design/icons";
 
 function App() {
   return (
     <BrowserRouter>
-      <GitHubBanner />
       <RefineKbarProvider>
         <ColorModeContextProvider>
           <AntdApp>
             <DevtoolsProvider>
               <Refine
-                dataProvider={dataProvider("https://api.fake-rest.refine.dev")}
+                dataProvider={dataProvider("http://localhost:8080/api/v1")}
                 notificationProvider={useNotificationProvider}
                 routerProvider={routerBindings}
                 authProvider={authProvider}
                 resources={[
                   {
-                    name: "blog_posts",
-                    list: "/blog-posts",
-                    create: "/blog-posts/create",
-                    edit: "/blog-posts/edit/:id",
-                    show: "/blog-posts/show/:id",
+                    name: "dashboard",
+                    list: "/dashboard",
+                    meta: {
+                      icon: <DashboardOutlined />,
+                      label: "Dashboard",
+                    },
+                  },
+                  {
+                    name: "deployments",
+                    list: "/deployments",
+                    create: "/deployments/create",
+                    show: "/deployments/show/:id",
+                    meta: {
+                      canDelete: true,
+                      icon: <span className="anticon">🚀</span>,
+                      label: "Deployments",
+                    },
+                  },
+                  {
+                    name: "templates",
+                    list: "/templates",
+                    create: "/templates/create",
+                    meta: {
+                      canDelete: true,
+                      icon: <span className="anticon">📄</span>,
+                      label: "Templates",
+                    },
+                  },
+                  {
+                    name: "apps",
+                    list: "/apps",
+                    create: "/apps/create",
+                    show: "/apps/show/:id",
                     meta: {
                       canDelete: true,
+                      icon: <AppstoreOutlined />,
+                      label: "Apps",
                     },
                   },
                   {
-                    name: "categories",
-                    list: "/categories",
-                    create: "/categories/create",
-                    edit: "/categories/edit/:id",
-                    show: "/categories/show/:id",
+                    name: "clients",
+                    list: "/clients",
+                    create: "/clients/create",
                     meta: {
                       canDelete: true,
+                      icon: <span className="anticon">👥</span>,
+                      label: "Clients",
+                    },
+                  },
+                  {
+                    name: "monitoring",
+                    list: "/monitoring",
+                    meta: {
+                      icon: <span className="anticon">📊</span>,
+                      label: "Monitoring",
+                    },
+                  },
+                  {
+                    name: "support",
+                    list: "/support",
+                    meta: {
+                      icon: <span className="anticon">🎫</span>,
+                      label: "Support Tickets",
                     },
                   },
                 ]}
@@ -88,7 +153,13 @@ function App() {
                       >
                         <ThemedLayoutV2
                           Header={Header}
-                          Sider={(props) => <ThemedSiderV2 {...props} fixed />}
+                          Sider={(props) => (
+                            <ThemedSiderV2
+                              {...props}
+                              fixed
+                              Title={() => <span>BYOP Dashboard</span>}
+                            />
+                          )}
                         >
                           <Outlet />
                         </ThemedLayoutV2>
@@ -97,19 +168,35 @@ function App() {
                   >
                     <Route
                       index
-                      element={<NavigateToResource resource="blog_posts" />}
+                      element={<NavigateToResource resource="dashboard" />}
                     />
-                    <Route path="/blog-posts">
-                      <Route index element={<BlogPostList />} />
-                      <Route path="create" element={<BlogPostCreate />} />
-                      <Route path="edit/:id" element={<BlogPostEdit />} />
-                      <Route path="show/:id" element={<BlogPostShow />} />
+                    <Route path="/dashboard">
+                      <Route index element={<DashboardOverview />} />
+                    </Route>
+                    <Route path="/deployments">
+                      <Route index element={<DeploymentList />} />
+                      <Route path="create" element={<DeploymentCreate />} />
+                      <Route path="show/:id" element={<DeploymentShow />} />
+                    </Route>
+                    <Route path="/templates">
+                      <Route index element={<TemplateList />} />
+                      <Route path="create" element={<TemplateCreate />} />
+                      <Route path="show/:id" element={<TemplateShow />} />
+                    </Route>
+                    <Route path="/apps">
+                      <Route index element={<AppList />} />
+                      <Route path="create" element={<AppCreate />} />
+                      <Route path="show/:id" element={<AppShow />} />
+                    </Route>
+                    <Route path="/clients">
+                      <Route index element={<ClientList />} />
+                      <Route path="create" element={<ClientCreate />} />
+                    </Route>
+                    <Route path="/monitoring">
+                      <Route index element={<MonitoringDashboard />} />
                     </Route>
-                    <Route path="/categories">
-                      <Route index element={<CategoryList />} />
-                      <Route path="create" element={<CategoryCreate />} />
-                      <Route path="edit/:id" element={<CategoryEdit />} />
-                      <Route path="show/:id" element={<CategoryShow />} />
+                    <Route path="/support">
+                      <Route index element={<SupportTickets />} />
                     </Route>
                     <Route path="*" element={<ErrorComponent />} />
                   </Route>

+ 249 - 26
src/authProvider.ts

@@ -1,59 +1,282 @@
 import type { AuthProvider } from "@refinedev/core";
+import axios from "axios";
 
-export const TOKEN_KEY = "refine-auth";
+export const TOKEN_KEY = "byop-auth";
+export const REFRESH_TOKEN_KEY = "byop-refresh";
+export const USER_KEY = "byop-user";
+
+// API base URL
+const API_URL = "http://localhost:8080/api/v1";
 
 export const authProvider: AuthProvider = {
-  login: async ({ username, email, password }) => {
-    if ((username || email) && password) {
-      localStorage.setItem(TOKEN_KEY, username);
+  login: async ({ email, password }) => {
+    if (!email || !password) {
       return {
-        success: true,
-        redirectTo: "/",
+        success: false,
+        error: {
+          name: "LoginError",
+          message: "Email and password are required",
+        },
       };
     }
 
-    return {
-      success: false,
-      error: {
-        name: "LoginError",
-        message: "Invalid username or password",
-      },
-    };
+    try {
+      const response = await axios.post(`${API_URL}/login`, {
+        email,
+        password,
+      });
+
+      if (response.data && response.data.token) {
+        // Store auth tokens
+        localStorage.setItem(TOKEN_KEY, response.data.token);
+        
+        // Store refresh token if available
+        if (response.data.refreshToken) {
+          localStorage.setItem(REFRESH_TOKEN_KEY, response.data.refreshToken);
+        }
+        
+        // Store user info
+        if (response.data.user) {
+          localStorage.setItem(USER_KEY, JSON.stringify(response.data.user));
+        }
+        
+        return {
+          success: true,
+          redirectTo: "/",
+        };
+      }
+
+      return {
+        success: false,
+        error: {
+          name: "LoginError",
+          message: "Invalid response from server",
+        },
+      };
+    } catch (error) {
+      const errorMessage = 
+        error.response?.data?.message || 
+        "Something went wrong. Please try again.";
+        
+      return {
+        success: false,
+        error: {
+          name: "LoginError",
+          message: errorMessage,
+        },
+      };
+    }
   },
+
+  register: async ({ username, email, password }) => {
+    if (!username || !email || !password) {
+      return {
+        success: false,
+        error: {
+          name: "RegisterError",
+          message: "Username, email, and password are required",
+        },
+      };
+    }
+
+    try {
+      const response = await axios.post(`${API_URL}/users`, {
+        username,
+        email,
+        password,
+        preferences: {
+          theme: "light",
+          notifications: true,
+        },
+      });
+
+      if (response.status === 201 || response.status === 200) {
+        return {
+          success: true,
+          redirectTo: "/login",
+        };
+      }
+
+      return {
+        success: false,
+        error: {
+          name: "RegisterError",
+          message: "Registration failed",
+        },
+      };
+    } catch (error) {
+      const errorMessage = 
+        error.response?.data?.message || 
+        "Something went wrong. Please try again.";
+      
+      return {
+        success: false,
+        error: {
+          name: "RegisterError",
+          message: errorMessage,
+        },
+      };
+    }
+  },
+
+  forgotPassword: async ({ email }) => {
+    if (!email) {
+      return {
+        success: false,
+        error: {
+          name: "ForgotPasswordError",
+          message: "Email is required",
+        },
+      };
+    }
+
+    try {
+      // Assuming your backend has a forgot-password endpoint
+      await axios.post(`${API_URL}/forgot-password`, { email });
+      
+      return {
+        success: true,
+      };
+    } catch (error) {
+      const errorMessage = 
+        error.response?.data?.message || 
+        "Something went wrong. Please try again.";
+      
+      return {
+        success: false,
+        error: {
+          name: "ForgotPasswordError",
+          message: errorMessage,
+        },
+      };
+    }
+  },
+
   logout: async () => {
-    localStorage.removeItem(TOKEN_KEY);
+    try {
+      // Call logout API endpoint with the current token
+      const token = localStorage.getItem(TOKEN_KEY);
+      if (token) {
+        await axios.post(
+          `${API_URL}/logout`,
+          {},
+          {
+            headers: {
+              Authorization: `Bearer ${token}`,
+            },
+          }
+        );
+      }
+    } catch (error) {
+      console.error("Logout error:", error);
+    } finally {
+      // Clear all auth-related storage
+      localStorage.removeItem(TOKEN_KEY);
+      localStorage.removeItem(REFRESH_TOKEN_KEY);
+      localStorage.removeItem(USER_KEY);
+    }
+    
     return {
       success: true,
       redirectTo: "/login",
     };
   },
+
   check: async () => {
     const token = localStorage.getItem(TOKEN_KEY);
-    if (token) {
+    if (!token) {
+      return {
+        authenticated: false,
+        redirectTo: "/login",
+      };
+    }
+
+    try {
+      // You could verify the token here by calling a protected endpoint
+      // Or just rely on the token's existence
       return {
         authenticated: true,
       };
+    } catch (error) {
+      return {
+        authenticated: false,
+        redirectTo: "/login",
+      };
     }
+  },
 
-    return {
-      authenticated: false,
-      redirectTo: "/login",
-    };
+  getPermissions: async () => {
+    const user = localStorage.getItem(USER_KEY);
+    if (user) {
+      const parsedUser = JSON.parse(user);
+      return parsedUser.role;
+    }
+    return null;
   },
-  getPermissions: async () => null,
+
   getIdentity: async () => {
-    const token = localStorage.getItem(TOKEN_KEY);
-    if (token) {
+    const user = localStorage.getItem(USER_KEY);
+    if (user) {
+      const parsedUser = JSON.parse(user);
       return {
-        id: 1,
-        name: "John Doe",
-        avatar: "https://i.pravatar.cc/300",
+        id: parsedUser.id,
+        name: parsedUser.username,
+        email: parsedUser.email,
+        role: parsedUser.role,
+        avatar: `https://ui-avatars.com/api/?name=${encodeURIComponent(parsedUser.username)}`,
+        preferences: parsedUser.preferences,
       };
     }
     return null;
   },
+
   onError: async (error) => {
-    console.error(error);
+    const status = error?.response?.status;
+    
+    if (status === 401) {
+      // Handle token expiration
+      const refreshToken = localStorage.getItem(REFRESH_TOKEN_KEY);
+      
+      if (refreshToken) {
+        try {
+          // Try to refresh the token
+          const response = await axios.post(`${API_URL}/refresh-token`, {
+            refreshToken,
+          });
+          
+          if (response.data && response.data.token) {
+            // Update the token
+            localStorage.setItem(TOKEN_KEY, response.data.token);
+            
+            // Return to prevent redirecting to login
+            return {
+              error,
+              logout: false,
+            };
+          }
+        } catch (refreshError) {
+          // If refresh fails, clear tokens and redirect to login
+          localStorage.removeItem(TOKEN_KEY);
+          localStorage.removeItem(REFRESH_TOKEN_KEY);
+          localStorage.removeItem(USER_KEY);
+          
+          return {
+            error,
+            logout: true,
+            redirectTo: "/login",
+          };
+        }
+      }
+      
+      return {
+        error,
+        logout: true,
+        redirectTo: "/login",
+      };
+    }
+    
+    // Handle other errors
+    console.error("API Error:", error);
     return { error };
   },
 };

+ 117 - 6
src/components/header/index.tsx

@@ -7,17 +7,31 @@ import {
   Switch,
   theme,
   Typography,
+  Button,
+  Badge,
+  Dropdown,
+  MenuProps,
+  Tooltip
 } from "antd";
 import React, { useContext } from "react";
 import { ColorModeContext } from "../../contexts/color-mode";
+import { 
+  BellOutlined, 
+  QuestionCircleOutlined,
+  SettingOutlined,
+  UserOutlined,
+  LogoutOutlined,
+  RocketOutlined
+} from "@ant-design/icons";
 
-const { Text } = Typography;
+const { Text, Title } = Typography;
 const { useToken } = theme;
 
 type IUser = {
   id: number;
   name: string;
   avatar: string;
+  role?: string;
 };
 
 export const Header: React.FC<RefineThemedLayoutV2HeaderProps> = ({
@@ -30,10 +44,11 @@ export const Header: React.FC<RefineThemedLayoutV2HeaderProps> = ({
   const headerStyles: React.CSSProperties = {
     backgroundColor: token.colorBgElevated,
     display: "flex",
-    justifyContent: "flex-end",
+    justifyContent: "space-between",
     alignItems: "center",
     padding: "0px 24px",
     height: "64px",
+    boxShadow: "0 2px 4px rgba(0,0,0,0.08)",
   };
 
   if (sticky) {
@@ -41,20 +56,116 @@ export const Header: React.FC<RefineThemedLayoutV2HeaderProps> = ({
     headerStyles.top = 0;
     headerStyles.zIndex = 1;
   }
+  
+  const userMenuItems: MenuProps["items"] = [
+    {
+      key: "profile",
+      icon: <UserOutlined />,
+      label: "Profile",
+    },
+    {
+      key: "settings",
+      icon: <SettingOutlined />,
+      label: "Settings",
+    },
+    {
+      type: "divider",
+    },
+    {
+      key: "logout",
+      icon: <LogoutOutlined />,
+      label: "Logout",
+      danger: true,
+    },
+  ];
+  
+  const notificationItems: MenuProps["items"] = [
+    {
+      key: "1",
+      label: (
+        <div>
+          <Text strong>New client deployment</Text>
+          <div>Acme Corp SAAS deployment is now active</div>
+          <Text type="secondary" style={{ fontSize: '12px' }}>5 minutes ago</Text>
+        </div>
+      ),
+    },
+    {
+      key: "2",
+      label: (
+        <div>
+          <Text strong>Alert: High CPU Usage</Text>
+          <div>Client XYZ experiencing high resource utilization</div>
+          <Text type="secondary" style={{ fontSize: '12px' }}>20 minutes ago</Text>
+        </div>
+      ),
+    },
+    {
+      type: "divider",
+    },
+    {
+      key: "view-all",
+      label: "View all notifications",
+    },
+  ];
 
   return (
     <AntdLayout.Header style={headerStyles}>
+      <div style={{ display: "flex", alignItems: "center" }}>
+        <RocketOutlined style={{ fontSize: '24px', marginRight: '8px', color: token.colorPrimary }} />
+        <Title level={4} style={{ margin: 0, marginRight: '24px' }}>BYOP</Title>
+        <Text type="secondary">SAAS Deployment Automation Platform</Text>
+      </div>
+      
       <Space>
+        <Tooltip title="Help & Resources">
+          <Button
+            type="text"
+            icon={<QuestionCircleOutlined style={{ fontSize: '18px' }} />}
+          />
+        </Tooltip>
+        
+        <Dropdown
+          menu={{ items: notificationItems }}
+          placement="bottomRight"
+          arrow
+        >
+          <Badge count={2}>
+            <Button
+              type="text" 
+              icon={<BellOutlined style={{ fontSize: '18px' }} />}
+            />
+          </Badge>
+        </Dropdown>
+        
         <Switch
           checkedChildren="🌛"
           unCheckedChildren="🔆"
           onChange={() => setMode(mode === "light" ? "dark" : "light")}
           defaultChecked={mode === "dark"}
         />
-        <Space style={{ marginLeft: "8px" }} size="middle">
-          {user?.name && <Text strong>{user.name}</Text>}
-          {user?.avatar && <Avatar src={user?.avatar} alt={user?.name} />}
-        </Space>
+        
+        <Dropdown menu={{ items: userMenuItems }} placement="bottomRight">
+          <Space style={{ marginLeft: "16px", cursor: "pointer" }}>
+            {user?.name && (
+              <div style={{ textAlign: "right" }}>
+                <Text strong>{user.name}</Text>
+                {user?.role && (
+                  <div>
+                    <Text type="secondary" style={{ fontSize: "12px" }}>
+                      {user.role}
+                    </Text>
+                  </div>
+                )}
+              </div>
+            )}
+            {user?.avatar ? (
+              <Avatar src={user?.avatar} alt={user?.name} />
+            ) : (
+              <Avatar icon={<UserOutlined />} />
+            )}
+          </Space>
+        </Dropdown>
       </Space>
     </AntdLayout.Header>
   );

+ 163 - 0
src/pages/apps/create.tsx

@@ -0,0 +1,163 @@
+import { Create, useForm } from "@refinedev/antd";
+import { Form, Input, Select, Tabs } from "antd";
+import { useState } from "react";
+import { AppFormData, AppType } from "../../types/app";
+
+const { TabPane } = Tabs;
+
+export const AppCreate = () => {
+  const { formProps, saveButtonProps } = useForm<AppFormData>({});
+  const [appType, setAppType] = useState<AppType>("frontend");
+
+  const handleTypeChange = (value: AppType) => {
+    setAppType(value);
+  };
+
+  return (
+    <Create saveButtonProps={saveButtonProps}>
+      <Form {...formProps} layout="vertical">
+        <Form.Item
+          label={"App Name"}
+          name="name"
+          rules={[{ required: true }]}
+        >
+          <Input />
+        </Form.Item>
+
+        <Form.Item
+          label={"Description"}
+          name="description"
+          rules={[{ required: true }]}
+        >
+          <Input.TextArea rows={3} />
+        </Form.Item>
+
+        <Form.Item
+          label={"App Type"}
+          name="type"
+          initialValue="frontend"
+          rules={[{ required: true }]}
+        >
+          <Select
+            options={[
+              { value: "frontend", label: "Frontend Application" },
+              { value: "backend", label: "Backend Service" },
+              { value: "api", label: "API Service" },
+              { value: "database", label: "Database" },
+              { value: "microservice", label: "Microservice" },
+            ]}
+            onChange={handleTypeChange}
+          />
+        </Form.Item>
+
+        <Form.Item
+          label={"Language/Framework"}
+          name="language"
+          rules={[{ required: true }]}
+        >
+          <Select
+            options={
+              appType === "frontend" 
+                ? [
+                  { value: "reactjs", label: "React JS" },
+                  { value: "vuejs", label: "Vue JS" },
+                  { value: "angular", label: "Angular" },
+                  { value: "nextjs", label: "Next.js" },
+                ] 
+                : appType === "database"
+                ? [
+                  { value: "postgresql", label: "PostgreSQL" },
+                  { value: "mysql", label: "MySQL" },
+                  { value: "mongodb", label: "MongoDB" },
+                  { value: "redis", label: "Redis" },
+                ]
+                : [
+                  { value: "nodejs", label: "Node.js" },
+                  { value: "python", label: "Python" },
+                  { value: "java", label: "Java" },
+                  { value: "golang", label: "Go" },
+                  { value: "dotnet", label: ".NET Core" },
+                ]
+            }
+          />
+        </Form.Item>
+
+        <Form.Item
+          label={"Version"}
+          name="version"
+          initialValue={"1.0.0"}
+          rules={[{ required: true }]}
+        >
+          <Input />
+        </Form.Item>
+
+        <Tabs defaultActiveKey="configuration">
+          <TabPane tab="Configuration" key="configuration">
+            <Form.Item
+              label={"Configuration File"}
+              name="configFile"
+              rules={[{ required: true }]}
+            >
+              <Input.TextArea rows={10} placeholder={
+                appType === "frontend" 
+                  ? `{\n  "name": "frontend-app",\n  "port": 3000,\n  "environment": "production",\n  "resources": {\n    "cpu": "0.5",\n    "memory": "512Mi"\n  }\n}`
+                  : appType === "backend" || appType === "api"
+                  ? `{\n  "name": "api-service",\n  "port": 8080,\n  "environment": "production",\n  "resources": {\n    "cpu": "1",\n    "memory": "1Gi"\n  },\n  "scaling": {\n    "min": 2,\n    "max": 5\n  }\n}`
+                  : `{\n  "name": "database",\n  "type": "postgres",\n  "version": "13",\n  "storage": "10Gi",\n  "backups": true\n}`
+              } />
+            </Form.Item>
+          </TabPane>
+
+          <TabPane tab="Environment Variables" key="env-vars">
+            <Form.Item
+              label={"Environment Variables"}
+              name="envVariables"
+            >
+              <Input.TextArea rows={5} placeholder={`PORT=8080\nNODE_ENV=production\nDATABASE_URL=postgresql://user:password@localhost:5432/db\nAPI_KEY=your-api-key`} />
+            </Form.Item>
+          </TabPane>
+
+          <TabPane tab="Source Code" key="source-code">
+            <Form.Item
+              label={"Source Code Repository"}
+              name="repository"
+            >
+              <Input placeholder="https://github.com/username/repo" />
+            </Form.Item>
+            
+            <Form.Item
+              label={"Branch"}
+              name="branch"
+              initialValue={"main"}
+            >
+              <Input />
+            </Form.Item>
+
+            <Form.Item
+              label={"Build Command"}
+              name="buildCommand"
+            >
+              <Input placeholder="npm install && npm run build" />
+            </Form.Item>
+          </TabPane>
+
+          <TabPane tab="Advanced Settings" key="advanced">
+            <Form.Item
+              label={"Resource Requirements"}
+              name="resources"
+            >
+              <Input.TextArea rows={4} placeholder={`CPU: 0.5\nMemory: 512Mi\nStorage: 1Gi`} />
+            </Form.Item>
+            
+            <Form.Item
+              label={"Scale Settings"}
+              name="scaleSettings"
+            >
+              <Input.TextArea rows={3} placeholder={`Min Instances: 2\nMax Instances: 5\nCPU Threshold: 75%`} />
+            </Form.Item>
+          </TabPane>
+        </Tabs>
+      </Form>
+    </Create>
+  );
+}

+ 2 - 2
src/pages/categories/index.ts → src/pages/apps/index.ts

@@ -1,4 +1,4 @@
-export * from "./create";
-export * from "./edit";
 export * from "./list";
+export * from "./create";
 export * from "./show";
+

+ 74 - 0
src/pages/apps/list.tsx

@@ -0,0 +1,74 @@
+import {
+  DeleteButton,
+  EditButton,
+  List,
+  ShowButton,
+  useTable,
+  TagField,
+} from "@refinedev/antd";
+import type { BaseRecord } from "@refinedev/core";
+import { Space, Table, Tag, Button, Typography } from "antd";
+import { PlusOutlined, AppstoreOutlined } from "@ant-design/icons";
+
+const { Title } = Typography;
+
+export const AppList = () => {
+  const { tableProps } = useTable({
+    syncWithLocation: true,
+  });
+
+  return (
+    <>
+      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 16 }}>
+        <Title level={4}>Apps</Title>
+        <Button type="primary" icon={<PlusOutlined />} href="/apps/create">
+          Create New App
+        </Button>
+      </div>
+
+      <List>
+        <Table {...tableProps} rowKey="id">
+          <Table.Column dataIndex="id" title="ID" />
+          <Table.Column dataIndex="name" title="App Name" />
+          <Table.Column dataIndex="description" title="Description" />
+          <Table.Column 
+            dataIndex="type" 
+            title="App Type" 
+            render={(value) => {
+              const colorMap: Record<string, string> = {
+                frontend: 'blue',
+                backend: 'green',
+                api: 'purple',
+                database: 'orange',
+                microservice: 'cyan',
+              };
+              
+              return (
+                <Tag color={colorMap[value] || 'default'}>
+                  {value?.toUpperCase()}
+                </Tag>
+              );
+            }}
+          />
+          <Table.Column 
+            dataIndex="language" 
+            title="Language/Framework"
+            render={(value) => <TagField value={value} />}
+          />
+          <Table.Column dataIndex="version" title="Version" />
+          <Table.Column
+            title="Actions"
+            dataIndex="actions"
+            render={(_, record: BaseRecord) => (
+              <Space>
+                <ShowButton hideText size="small" recordItemId={record.id} />
+                <EditButton hideText size="small" recordItemId={record.id} />
+                <DeleteButton hideText size="small" recordItemId={record.id} />
+              </Space>
+            )}
+          />
+        </Table>
+      </List>
+    </>
+  );
+};

+ 171 - 0
src/pages/apps/show.tsx

@@ -0,0 +1,171 @@
+import { Show, TextField, TagField } from "@refinedev/antd";
+import { useShow } from "@refinedev/core";
+import { Typography, Card, Descriptions, Tabs, Badge, Divider, Button, Row, Col, Tag, Alert } from "antd";
+import { CodeOutlined, BranchesOutlined, ApiOutlined, DatabaseOutlined } from '@ant-design/icons';
+
+const { Title, Text } = Typography;
+const { TabPane } = Tabs;
+
+export const AppShow = () => {
+  const { queryResult } = useShow({});
+  const { data, isLoading } = queryResult;
+  const record = data?.data;
+
+  // Function to get an icon based on app type
+  const getAppTypeIcon = (type: string) => {
+    switch (type) {
+      case 'frontend':
+        return <span role="img" aria-label="frontend">🖥️</span>;
+      case 'backend':
+        return <span role="img" aria-label="backend">⚙️</span>;
+      case 'api':
+        return <ApiOutlined />;
+      case 'database':
+        return <DatabaseOutlined />;
+      case 'microservice':
+        return <CodeOutlined />;
+      default:
+        return <CodeOutlined />;
+    }
+  };
+
+  // Function to display color tag based on app type
+  const getAppTypeTag = (type: string) => {
+    const colorMap: Record<string, string> = {
+      frontend: 'blue',
+      backend: 'green',
+      api: 'purple',
+      database: 'orange',
+      microservice: 'cyan',
+    };
+    
+    return (
+      <Tag color={colorMap[type] || 'default'}>
+        {type?.toUpperCase()}
+      </Tag>
+    );
+  };
+  
+  return (
+    <Show isLoading={isLoading} 
+      headerButtons={
+        <>
+          <Button type="primary">Deploy App</Button>
+          <Button>Edit App</Button>
+        </>
+      }
+    >
+      <Title level={5}>App Information</Title>
+      
+      <Card>
+        <Descriptions bordered column={2}>
+          <Descriptions.Item label="App Name">{record?.name}</Descriptions.Item>
+          <Descriptions.Item label="Type">
+            {record?.type && (
+              <div>
+                {getAppTypeIcon(record.type)}{' '}
+                {getAppTypeTag(record.type)}
+              </div>
+            )}
+          </Descriptions.Item>
+          <Descriptions.Item label="Language/Framework">
+            <TagField value={record?.language} />
+          </Descriptions.Item>
+          <Descriptions.Item label="Version">{record?.version}</Descriptions.Item>
+          <Descriptions.Item label="Description" span={2}>
+            {record?.description}
+          </Descriptions.Item>
+        </Descriptions>
+      </Card>
+
+      <Divider />
+      
+      <Tabs defaultActiveKey="config">
+        <TabPane 
+          tab={<span><CodeOutlined /> Configuration</span>} 
+          key="config"
+        >
+          <Card title="App Configuration">
+            <pre style={{ backgroundColor: '#f5f5f5', padding: 16, borderRadius: 4 }}>
+              {record?.configFile || '{\n  // No configuration available\n}'}
+            </pre>
+          </Card>
+        </TabPane>
+        
+        <TabPane 
+          tab={<span><BranchesOutlined /> Environment</span>} 
+          key="env"
+        >
+          <Card title="Environment Variables">
+            {record?.envVariables ? (
+              <pre style={{ backgroundColor: '#f5f5f5', padding: 16, borderRadius: 4 }}>
+                {record.envVariables}
+              </pre>
+            ) : (
+              <Alert message="No environment variables have been defined" type="info" />
+            )}
+          </Card>
+        </TabPane>
+        
+        <TabPane 
+          tab={<span><CodeOutlined /> Source Code</span>} 
+          key="source"
+        >
+          <Card>
+            <Row gutter={16}>
+              <Col span={12}>
+                <Descriptions title="Repository Information" bordered column={1}>
+                  <Descriptions.Item label="Repository URL">
+                    {record?.repository || 'Not specified'}
+                  </Descriptions.Item>
+                  <Descriptions.Item label="Branch">
+                    {record?.branch || 'main'}
+                  </Descriptions.Item>
+                  <Descriptions.Item label="Build Command">
+                    {record?.buildCommand || 'Not specified'}
+                  </Descriptions.Item>
+                </Descriptions>
+              </Col>
+              <Col span={12}>
+                <Card title="Last Commit" bordered={false}>
+                  <Alert 
+                    message="Source code tracking not enabled" 
+                    description="Connect your repository to track commits and build status"
+                    type="info"
+                  />
+                </Card>
+              </Col>
+            </Row>
+          </Card>
+        </TabPane>
+        
+        <TabPane 
+          tab={<span>⚙️ Resources</span>} 
+          key="resources"
+        >
+          <Card title="Resource Allocation">
+            {record?.resources ? (
+              <pre style={{ backgroundColor: '#f5f5f5', padding: 16, borderRadius: 4 }}>
+                {record.resources}
+              </pre>
+            ) : (
+              <Alert message="No resource requirements specified" type="info" />
+            )}
+          </Card>
+          
+          {record?.type !== 'database' && (
+            <Card title="Scaling Configuration" style={{ marginTop: 16 }}>
+              {record?.scaleSettings ? (
+                <pre style={{ backgroundColor: '#f5f5f5', padding: 16, borderRadius: 4 }}>
+                  {record.scaleSettings}
+                </pre>
+              ) : (
+                <Alert message="No scaling settings defined" type="info" />
+              )}
+            </Card>
+          )}
+        </TabPane>
+      </Tabs>
+    </Show>
+  );
+};

+ 0 - 71
src/pages/blog-posts/create.tsx

@@ -1,71 +0,0 @@
-import { Create, useForm, useSelect } from "@refinedev/antd";
-import MDEditor from "@uiw/react-md-editor";
-import { Form, Input, Select } from "antd";
-
-export const BlogPostCreate = () => {
-  const { formProps, saveButtonProps } = useForm({});
-
-  const { selectProps: categorySelectProps } = useSelect({
-    resource: "categories",
-  });
-
-  return (
-    <Create saveButtonProps={saveButtonProps}>
-      <Form {...formProps} layout="vertical">
-        <Form.Item
-          label={"Title"}
-          name={["title"]}
-          rules={[
-            {
-              required: true,
-            },
-          ]}
-        >
-          <Input />
-        </Form.Item>
-        <Form.Item
-          label={"Content"}
-          name="content"
-          rules={[
-            {
-              required: true,
-            },
-          ]}
-        >
-          <MDEditor data-color-mode="light" />
-        </Form.Item>
-        <Form.Item
-          label={"Category"}
-          name={["category", "id"]}
-          rules={[
-            {
-              required: true,
-            },
-          ]}
-        >
-          <Select {...categorySelectProps} />
-        </Form.Item>
-        <Form.Item
-          label={"Status"}
-          name={["status"]}
-          initialValue={"draft"}
-          rules={[
-            {
-              required: true,
-            },
-          ]}
-        >
-          <Select
-            defaultValue={"draft"}
-            options={[
-              { value: "draft", label: "Draft" },
-              { value: "published", label: "Published" },
-              { value: "rejected", label: "Rejected" },
-            ]}
-            style={{ width: 120 }}
-          />
-        </Form.Item>
-      </Form>
-    </Create>
-  );
-};

+ 0 - 78
src/pages/blog-posts/edit.tsx

@@ -1,78 +0,0 @@
-import { Edit, useForm, useSelect } from "@refinedev/antd";
-import MDEditor from "@uiw/react-md-editor";
-import { Form, Input, Select } from "antd";
-
-export const BlogPostEdit = () => {
-  const { formProps, saveButtonProps, queryResult, formLoading } = useForm({});
-
-  const blogPostsData = queryResult?.data?.data;
-
-  const { selectProps: categorySelectProps } = useSelect({
-    resource: "categories",
-    defaultValue: blogPostsData?.category,
-    queryOptions: {
-      enabled: !!blogPostsData?.category,
-    },
-  });
-
-  return (
-    <Edit saveButtonProps={saveButtonProps} isLoading={formLoading}>
-      <Form {...formProps} layout="vertical">
-        <Form.Item
-          label={"Title"}
-          name={["title"]}
-          rules={[
-            {
-              required: true,
-            },
-          ]}
-        >
-          <Input />
-        </Form.Item>
-        <Form.Item
-          label={"Content"}
-          name="content"
-          rules={[
-            {
-              required: true,
-            },
-          ]}
-        >
-          <MDEditor data-color-mode="light" />
-        </Form.Item>
-        <Form.Item
-          label={"Category"}
-          name={["category", "id"]}
-          initialValue={formProps?.initialValues?.category?.id}
-          rules={[
-            {
-              required: true,
-            },
-          ]}
-        >
-          <Select {...categorySelectProps} />
-        </Form.Item>
-        <Form.Item
-          label={"Status"}
-          name={["status"]}
-          initialValue={"draft"}
-          rules={[
-            {
-              required: true,
-            },
-          ]}
-        >
-          <Select
-            defaultValue={"draft"}
-            options={[
-              { value: "draft", label: "Draft" },
-              { value: "published", label: "Published" },
-              { value: "rejected", label: "Rejected" },
-            ]}
-            style={{ width: 120 }}
-          />
-        </Form.Item>
-      </Form>
-    </Edit>
-  );
-};

+ 0 - 73
src/pages/blog-posts/list.tsx

@@ -1,73 +0,0 @@
-import {
-  DateField,
-  DeleteButton,
-  EditButton,
-  List,
-  MarkdownField,
-  ShowButton,
-  useTable,
-} from "@refinedev/antd";
-import { type BaseRecord, useMany } from "@refinedev/core";
-import { Space, Table } from "antd";
-
-export const BlogPostList = () => {
-  const { tableProps } = useTable({
-    syncWithLocation: true,
-  });
-
-  const { data: categoryData, isLoading: categoryIsLoading } = useMany({
-    resource: "categories",
-    ids:
-      tableProps?.dataSource
-        ?.map((item) => item?.category?.id)
-        .filter(Boolean) ?? [],
-    queryOptions: {
-      enabled: !!tableProps?.dataSource,
-    },
-  });
-
-  return (
-    <List>
-      <Table {...tableProps} rowKey="id">
-        <Table.Column dataIndex="id" title={"ID"} />
-        <Table.Column dataIndex="title" title={"Title"} />
-        <Table.Column
-          dataIndex="content"
-          title={"Content"}
-          render={(value: any) => {
-            if (!value) return "-";
-            return <MarkdownField value={value.slice(0, 80) + "..."} />;
-          }}
-        />
-        <Table.Column
-          dataIndex={"category"}
-          title={"Category"}
-          render={(value) =>
-            categoryIsLoading ? (
-              <>Loading...</>
-            ) : (
-              categoryData?.data?.find((item) => item.id === value?.id)?.title
-            )
-          }
-        />
-        <Table.Column dataIndex="status" title={"Status"} />
-        <Table.Column
-          dataIndex={["createdAt"]}
-          title={"Created at"}
-          render={(value: any) => <DateField value={value} />}
-        />
-        <Table.Column
-          title={"Actions"}
-          dataIndex="actions"
-          render={(_, record: BaseRecord) => (
-            <Space>
-              <EditButton hideText size="small" recordItemId={record.id} />
-              <ShowButton hideText size="small" recordItemId={record.id} />
-              <DeleteButton hideText size="small" recordItemId={record.id} />
-            </Space>
-          )}
-        />
-      </Table>
-    </List>
-  );
-};

+ 0 - 41
src/pages/blog-posts/show.tsx

@@ -1,41 +0,0 @@
-import { DateField, MarkdownField, Show, TextField } from "@refinedev/antd";
-import { useOne, useShow } from "@refinedev/core";
-import { Typography } from "antd";
-
-const { Title } = Typography;
-
-export const BlogPostShow = () => {
-  const { queryResult } = useShow({});
-  const { data, isLoading } = queryResult;
-
-  const record = data?.data;
-
-  const { data: categoryData, isLoading: categoryIsLoading } = useOne({
-    resource: "categories",
-    id: record?.category?.id || "",
-    queryOptions: {
-      enabled: !!record,
-    },
-  });
-
-  return (
-    <Show isLoading={isLoading}>
-      <Title level={5}>{"ID"}</Title>
-      <TextField value={record?.id} />
-      <Title level={5}>{"Title"}</Title>
-      <TextField value={record?.title} />
-      <Title level={5}>{"Content"}</Title>
-      <MarkdownField value={record?.content} />
-      <Title level={5}>{"Category"}</Title>
-      <TextField
-        value={
-          categoryIsLoading ? <>Loading...</> : <>{categoryData?.data?.title}</>
-        }
-      />
-      <Title level={5}>{"Status"}</Title>
-      <TextField value={record?.status} />
-      <Title level={5}>{"CreatedAt"}</Title>
-      <DateField value={record?.createdAt} />
-    </Show>
-  );
-};

+ 0 - 24
src/pages/categories/create.tsx

@@ -1,24 +0,0 @@
-import { Create, useForm } from "@refinedev/antd";
-import { Form, Input } from "antd";
-
-export const CategoryCreate = () => {
-  const { formProps, saveButtonProps } = useForm({});
-
-  return (
-    <Create saveButtonProps={saveButtonProps}>
-      <Form {...formProps} layout="vertical">
-        <Form.Item
-          label={"Title"}
-          name={["title"]}
-          rules={[
-            {
-              required: true,
-            },
-          ]}
-        >
-          <Input />
-        </Form.Item>
-      </Form>
-    </Create>
-  );
-};

+ 0 - 24
src/pages/categories/edit.tsx

@@ -1,24 +0,0 @@
-import { Edit, useForm } from "@refinedev/antd";
-import { Form, Input } from "antd";
-
-export const CategoryEdit = () => {
-  const { formProps, saveButtonProps } = useForm({});
-
-  return (
-    <Edit saveButtonProps={saveButtonProps}>
-      <Form {...formProps} layout="vertical">
-        <Form.Item
-          label={"Title"}
-          name={["title"]}
-          rules={[
-            {
-              required: true,
-            },
-          ]}
-        >
-          <Input />
-        </Form.Item>
-      </Form>
-    </Edit>
-  );
-};

+ 0 - 21
src/pages/categories/show.tsx

@@ -1,21 +0,0 @@
-import { Show, TextField } from "@refinedev/antd";
-import { useShow } from "@refinedev/core";
-import { Typography } from "antd";
-
-const { Title } = Typography;
-
-export const CategoryShow = () => {
-  const { queryResult } = useShow({});
-  const { data, isLoading } = queryResult;
-
-  const record = data?.data;
-
-  return (
-    <Show isLoading={isLoading}>
-      <Title level={5}>{"ID"}</Title>
-      <TextField value={record?.id} />
-      <Title level={5}>{"Title"}</Title>
-      <TextField value={record?.title} />
-    </Show>
-  );
-};

+ 114 - 0
src/pages/clients/create.tsx

@@ -0,0 +1,114 @@
+import {
+  Form,
+  Input,
+  Select,
+} from "antd";
+import { Create, useForm } from "@refinedev/antd";
+import { Col, Row, Card } from "antd";
+import { ClientFormData, PlanType } from "../../types/client";
+
+export const ClientCreate = () => {
+  const { formProps, saveButtonProps } = useForm<ClientFormData>({
+    redirect: "list",
+    onMutationSuccess: (data) => {
+      console.log("Client created successfully:", data);
+    },
+    onMutationError: (error) => {
+      console.error("Error creating client:", error);
+    },
+  });
+
+  return (
+    <Create saveButtonProps={saveButtonProps}>
+      <Form {...formProps} layout="vertical">
+        <Card title="Client Information" style={{ marginBottom: 16 }}>
+          <Row gutter={16}>
+            <Col span={12}>
+              <Form.Item
+                label="Name"
+                name="name"
+                rules={[
+                  {
+                    required: true,
+                    message: "Please enter client name",
+                  },
+                ]}
+              >
+                <Input placeholder="Client name" />
+              </Form.Item>
+            </Col>
+            <Col span={12}>
+              <Form.Item
+                label="Organization"
+                name="organization"
+                rules={[
+                  {
+                    required: true,
+                    message: "Please enter organization name",
+                  },
+                ]}
+              >
+                <Input placeholder="Organization name" />
+              </Form.Item>
+            </Col>
+          </Row>
+          <Row gutter={16}>
+            <Col span={12}>
+              <Form.Item
+                label="Contact Email"
+                name="contactEmail"
+                rules={[
+                  {
+                    required: true,
+                    message: "Please enter contact email",
+                  },
+                  {
+                    type: "email",
+                    message: "Please enter a valid email",
+                  },
+                ]}
+              >
+                <Input placeholder="contact@example.com" />
+              </Form.Item>
+            </Col>
+            <Col span={12}>
+              <Form.Item
+                label="Contact Phone"
+                name="contactPhone"
+                rules={[
+                  {
+                    message: "Please enter a valid phone number",
+                    pattern: /^\+?[0-9()-\s]+$/,
+                  },
+                ]}
+              >
+                <Input placeholder="Phone number (optional)" />
+              </Form.Item>
+            </Col>
+          </Row>
+          <Row gutter={16}>
+            <Col span={12}>
+              <Form.Item
+                label="Plan"
+                name="plan"
+                initialValue="basic"
+                rules={[
+                  {
+                    required: true,
+                    message: "Please select a plan",
+                  },
+                ]}
+              >
+                <Select placeholder="Select a plan">
+                  <Select.Option value="basic">Basic</Select.Option>
+                  <Select.Option value="pro">Pro</Select.Option>
+                  <Select.Option value="enterprise">Enterprise</Select.Option>
+                </Select>
+              </Form.Item>
+            </Col>
+          </Row>
+        </Card>
+      </Form>
+    </Create>
+  );
+};

+ 2 - 0
src/pages/clients/index.ts

@@ -0,0 +1,2 @@
+export * from "./list";
+export * from "./create";

+ 63 - 0
src/pages/clients/list.tsx

@@ -0,0 +1,63 @@
+import {
+  CreateButton,
+  DeleteButton,
+  EditButton,
+  List,
+  ShowButton,
+  useTable,
+} from "@refinedev/antd";
+import type { BaseRecord } from "@refinedev/core";
+import { Space, Table, Tag } from "antd";
+
+export const ClientList = () => {
+  const { tableProps } = useTable({
+    syncWithLocation: true,
+  });
+
+  return (
+    <List 
+      headerButtons={[
+        <CreateButton key="create" />
+      ]}
+    >
+      <Table {...tableProps} rowKey="id">
+        <Table.Column dataIndex="id" title="ID" />
+        <Table.Column dataIndex="name" title="Client Name" />
+        <Table.Column dataIndex="contactEmail" title="Contact Email" />
+        <Table.Column dataIndex="organization" title="Organization" />
+        <Table.Column dataIndex="contactPhone" title="Phone" />
+        <Table.Column 
+          dataIndex="plan" 
+          title="Plan" 
+          render={(value) => {
+            let color = 'blue';
+            if (value === 'pro') {
+              color = 'purple';
+            } else if (value === 'enterprise') {
+              color = 'gold';
+            }
+            return <Tag color={color}>{value.toUpperCase()}</Tag>;
+          }}
+        />
+        <Table.Column
+          dataIndex="createdAt"
+          title="Created At"
+          render={(value) => {
+            return new Date(value).toLocaleDateString();
+          }}
+        />
+        <Table.Column
+          title="Actions"
+          dataIndex="actions"
+          render={(_, record: BaseRecord) => (
+            <Space>
+              <ShowButton hideText size="small" recordItemId={record.id} />
+              <EditButton hideText size="small" recordItemId={record.id} />
+              <DeleteButton hideText size="small" recordItemId={record.id} />
+            </Space>
+          )}
+        />
+      </Table>
+    </List>
+  );
+};

+ 1 - 0
src/pages/dashboard/index.ts

@@ -0,0 +1 @@
+export * from "./overview";

+ 314 - 0
src/pages/dashboard/overview.tsx

@@ -0,0 +1,314 @@
+import { useList } from "@refinedev/core";
+import { 
+  Card, 
+  Row, 
+  Col, 
+  Typography, 
+  Statistic, 
+  Table, 
+  Progress, 
+  Timeline,
+  Space,
+  Button,
+  Tag,
+  Divider 
+} from "antd";
+import {
+  RocketOutlined,
+  UserOutlined,
+  FileOutlined,
+  CheckCircleOutlined,
+  WarningOutlined,
+  ClockCircleOutlined,
+  PlusOutlined
+} from "@ant-design/icons";
+import {
+  AreaChart,
+  Area,
+  XAxis,
+  YAxis,
+  CartesianGrid,
+  Tooltip,
+  ResponsiveContainer,
+  PieChart,
+  Pie,
+  Cell
+} from "recharts";
+
+const { Title, Text } = Typography;
+
+// Mock data for charts
+const deploymentTrendData = [
+  { name: "Jan", deployments: 10 },
+  { name: "Feb", deployments: 15 },
+  { name: "Mar", deployments: 20 },
+  { name: "Apr", deployments: 25 },
+  { name: "May", deployments: 40 },
+];
+
+const templateUsageData = [
+  { name: "Docker", value: 45 },
+  { name: "Docker Compose", value: 35 },
+  { name: "Kubernetes", value: 20 },
+];
+
+const COLORS = ["#0088FE", "#00C49F", "#FFBB28"];
+
+export const DashboardOverview = () => {
+  // In a real implementation, these would come from API calls
+  const { data: deploymentsData } = useList({
+    resource: "deployments",
+  });
+
+  const { data: clientsData } = useList({
+    resource: "clients",
+  });
+
+  const { data: templatesData } = useList({
+    resource: "templates",
+  });
+
+  // Calculate summary statistics
+  const totalDeployments = deploymentsData?.data?.length || 0;
+  const activeDeployments = deploymentsData?.data?.filter(item => item.status === "active")?.length || 0;
+  const totalClients = clientsData?.data?.length || 0;
+  const totalTemplates = templatesData?.data?.length || 0;
+  
+  // Mock recent deployments data
+  const recentDeployments = [
+    { id: 1, name: "Acme Corp CRM", clientName: "Acme Corp", status: "active", date: "2025-05-08 14:30" },
+    { id: 2, name: "GlobalTech ERP", clientName: "GlobalTech", status: "pending", date: "2025-05-08 10:15" },
+    { id: 3, name: "InnoSoft Analytics", clientName: "InnoSoft", status: "active", date: "2025-05-07 16:45" },
+  ];
+
+  // Mock recent activity data
+  const recentActivity = [
+    { id: 1, action: "Deployment created", target: "Acme Corp CRM", user: "John Admin", time: "2025-05-08 14:25" },
+    { id: 2, action: "Template updated", target: "Node.js Microservice", user: "Sarah Developer", time: "2025-05-08 11:30" },
+    { id: 3, action: "Client onboarded", target: "GlobalTech", user: "John Admin", time: "2025-05-08 09:45" },
+    { id: 4, action: "Support ticket resolved", target: "#1234", user: "Mike Support", time: "2025-05-07 17:20" },
+  ];
+
+  return (
+    <>
+      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 16 }}>
+        <Title level={4}>BYOP Dashboard Overview</Title>
+        <Space>
+          <Button icon={<PlusOutlined />} type="primary">
+            New Deployment
+          </Button>
+        </Space>
+      </div>
+
+      {/* Summary Statistics */}
+      <Row gutter={[16, 16]}>
+        <Col xs={24} sm={12} md={6}>
+          <Card>
+            <Statistic
+              title="Total Deployments"
+              value={totalDeployments}
+              prefix={<RocketOutlined />}
+              valueStyle={{ color: "#3f8600" }}
+            />
+            <div style={{ marginTop: 8 }}>
+              <Text type="secondary">{activeDeployments} active</Text>
+            </div>
+          </Card>
+        </Col>
+        <Col xs={24} sm={12} md={6}>
+          <Card>
+            <Statistic
+              title="Total Clients"
+              value={totalClients}
+              prefix={<UserOutlined />}
+              valueStyle={{ color: "#1890ff" }}
+            />
+            <div style={{ marginTop: 8 }}>
+              <Text type="secondary">Across multiple industries</Text>
+            </div>
+          </Card>
+        </Col>
+        <Col xs={24} sm={12} md={6}>
+          <Card>
+            <Statistic
+              title="Deployment Templates"
+              value={totalTemplates}
+              prefix={<FileOutlined />}
+              valueStyle={{ color: "#722ed1" }}
+            />
+            <div style={{ marginTop: 8 }}>
+              <Text type="secondary">Ready for deployment</Text>
+            </div>
+          </Card>
+        </Col>
+        <Col xs={24} sm={12} md={6}>
+          <Card>
+            <Statistic
+              title="System Health"
+              value="98%"
+              prefix={<CheckCircleOutlined />}
+              valueStyle={{ color: "#3f8600" }}
+            />
+            <div style={{ marginTop: 8 }}>
+              <Progress percent={98} size="small" showInfo={false} />
+            </div>
+          </Card>
+        </Col>
+      </Row>
+
+      <Row gutter={[16, 16]} style={{ marginTop: 16 }}>
+        {/* Deployment Trends */}
+        <Col xs={24} lg={12}>
+          <Card title="Deployment Trends">
+            <ResponsiveContainer width="100%" height={250}>
+              <AreaChart
+                data={deploymentTrendData}
+                margin={{ top: 10, right: 30, left: 0, bottom: 0 }}
+              >
+                <CartesianGrid strokeDasharray="3 3" />
+                <XAxis dataKey="name" />
+                <YAxis />
+                <Tooltip />
+                <Area type="monotone" dataKey="deployments" stroke="#8884d8" fill="#8884d8" />
+              </AreaChart>
+            </ResponsiveContainer>
+          </Card>
+        </Col>
+
+        {/* Template Usage */}
+        <Col xs={24} lg={12}>
+          <Card title="Template Usage">
+            <Row>
+              <Col span={12}>
+                <ResponsiveContainer width="100%" height={250}>
+                  <PieChart>
+                    <Pie
+                      data={templateUsageData}
+                      cx="50%"
+                      cy="50%"
+                      labelLine={false}
+                      outerRadius={80}
+                      fill="#8884d8"
+                      dataKey="value"
+                      label={({ name, percent }) => `${name} ${(percent * 100).toFixed(0)}%`}
+                    >
+                      {templateUsageData.map((entry, index) => (
+                        <Cell key={`cell-${index}`} fill={COLORS[index % COLORS.length]} />
+                      ))}
+                    </Pie>
+                    <Tooltip />
+                  </PieChart>
+                </ResponsiveContainer>
+              </Col>
+              <Col span={12}>
+                <div style={{ paddingLeft: 20 }}>
+                  {templateUsageData.map((item, index) => (
+                    <div key={item.name} style={{ marginBottom: 10 }}>
+                      <div style={{ display: "flex", alignItems: "center" }}>
+                        <div
+                          style={{
+                            width: 10,
+                            height: 10,
+                            backgroundColor: COLORS[index % COLORS.length],
+                            marginRight: 8,
+                          }}
+                        />
+                        <Text>{item.name}</Text>
+                      </div>
+                      <Text type="secondary">{item.value} deployments</Text>
+                    </div>
+                  ))}
+                </div>
+              </Col>
+            </Row>
+          </Card>
+        </Col>
+      </Row>
+
+      <Row gutter={[16, 16]} style={{ marginTop: 16 }}>
+        {/* Recent Deployments */}
+        <Col xs={24} lg={12}>
+          <Card title="Recent Deployments" extra={<Button type="link">View All</Button>}>
+            <Table
+              dataSource={recentDeployments}
+              pagination={false}
+              rowKey="id"
+              size="small"
+              columns={[
+                { title: "Name", dataIndex: "name", key: "name", render: (text) => <Text strong>{text}</Text> },
+                { title: "Client", dataIndex: "clientName", key: "clientName" },
+                { 
+                  title: "Status", 
+                  dataIndex: "status",
+                  key: "status",
+                  render: (status) => (
+                    status === "active" ? 
+                      <Tag color="green">Active</Tag> : 
+                      <Tag color="orange">Pending</Tag>
+                  )
+                },
+                { title: "Date", dataIndex: "date", key: "date" },
+              ]}
+            />
+          </Card>
+        </Col>
+
+        {/* Recent Activity */}
+        <Col xs={24} lg={12}>
+          <Card title="Recent Activity" extra={<Button type="link">View All</Button>}>
+            <Timeline
+              items={recentActivity.map(item => ({
+                dot: item.action.includes("Deployment") ? <RocketOutlined style={{ color: "#1890ff" }} /> : 
+                     item.action.includes("Template") ? <FileOutlined style={{ color: "#722ed1" }} /> :
+                     item.action.includes("Client") ? <UserOutlined style={{ color: "#52c41a" }} /> :
+                     <ClockCircleOutlined style={{ color: "#faad14" }} />,
+                children: (
+                  <>
+                    <Text strong>{item.action}</Text>
+                    <div>{item.target}</div>
+                    <div>
+                      <Text type="secondary">{item.user} - {item.time}</Text>
+                    </div>
+                  </>
+                )
+              }))}
+            />
+          </Card>
+        </Col>
+      </Row>
+
+      <Row gutter={[16, 16]} style={{ marginTop: 16 }}>
+        <Col span={24}>
+          <Card title="System Alerts" extra={<Button type="link">View All</Button>}>
+            <Timeline
+              items={[
+                {
+                  dot: <WarningOutlined style={{ color: "#ff4d4f" }} />,
+                  color: "red",
+                  children: (
+                    <>
+                      <Text strong>High CPU Usage</Text>
+                      <div>Client: GlobalTech ERP - Container CPU usage exceeds 90%</div>
+                      <div><Text type="secondary">2025-05-08 13:45</Text></div>
+                    </>
+                  )
+                },
+                {
+                  dot: <WarningOutlined style={{ color: "#faad14" }} />,
+                  color: "orange",
+                  children: (
+                    <>
+                      <Text strong>Database Memory Usage</Text>
+                      <div>Client: InnoSoft Analytics - Database memory utilization above 75%</div>
+                      <div><Text type="secondary">2025-05-08 12:30</Text></div>
+                    </>
+                  )
+                }
+              ]}
+            />
+          </Card>
+        </Col>
+      </Row>
+    </>
+  );
+};

+ 80 - 0
src/pages/deployments/create.tsx

@@ -0,0 +1,80 @@
+import { Create, useForm, useSelect } from "@refinedev/antd";
+import { Form, Input, Select, InputNumber, Divider } from "antd";
+import { DeploymentFormData, Environment } from "../../types/deployment";
+
+export const DeploymentCreate = () => {
+  const { formProps, saveButtonProps } = useForm<DeploymentFormData>({});
+
+  const { selectProps: clientSelectProps } = useSelect({
+    resource: "clients",
+  });
+
+  const { selectProps: templateSelectProps } = useSelect({
+    resource: "templates",
+  });
+
+  return (
+    <Create saveButtonProps={saveButtonProps}>
+      <Form {...formProps} layout="vertical">
+        <Form.Item
+          label={"Deployment Name"}
+          name="name"
+          rules={[{ required: true }]}
+        >
+          <Input />
+        </Form.Item>
+
+        <Form.Item
+          label={"Client"}
+          name="clientId"
+          rules={[{ required: true }]}
+        >
+          <Select {...clientSelectProps} placeholder="Select client" />
+        </Form.Item>
+
+        <Form.Item
+          label={"Template"}
+          name="templateId"
+          rules={[{ required: true }]}
+        >
+          <Select {...templateSelectProps} placeholder="Select template" />
+        </Form.Item>
+
+        <Divider>Configuration</Divider>
+
+        <Form.Item
+          label={"Version"}
+          name="version"
+          initialValue={"1.0.0"}
+          rules={[{ required: true }]}
+        >
+          <Input />
+        </Form.Item>
+
+        <Form.Item
+          label={"Container Instances"}
+          name="containerCount"
+          initialValue={1}
+          rules={[{ required: true }]}
+        >
+          <InputNumber min={1} max={10} />
+        </Form.Item>
+
+        <Form.Item
+          label={"Environment"}
+          name="environment"
+          initialValue={"production"}
+          rules={[{ required: true }]}
+        >
+          <Select
+            options={[
+              { value: "development", label: "Development" },
+              { value: "staging", label: "Staging" },
+              { value: "production", label: "Production" },
+            ]}
+          />
+        </Form.Item>
+      </Form>
+    </Create>
+  );
+};

+ 1 - 2
src/pages/blog-posts/index.ts → src/pages/deployments/index.ts

@@ -1,4 +1,3 @@
 export * from "./create";
-export * from "./edit";
 export * from "./list";
-export * from "./show";
+export * from "./show";

+ 22 - 5
src/pages/categories/list.tsx → src/pages/deployments/list.tsx

@@ -4,11 +4,12 @@ import {
   List,
   ShowButton,
   useTable,
+  TagField,
 } from "@refinedev/antd";
 import type { BaseRecord } from "@refinedev/core";
-import { Space, Table } from "antd";
+import { Space, Table, Tag } from "antd";
 
-export const CategoryList = () => {
+export const DeploymentList = () => {
   const { tableProps } = useTable({
     syncWithLocation: true,
   });
@@ -17,14 +18,30 @@ export const CategoryList = () => {
     <List>
       <Table {...tableProps} rowKey="id">
         <Table.Column dataIndex="id" title={"ID"} />
-        <Table.Column dataIndex="title" title={"title"} />
+        <Table.Column dataIndex="name" title={"Deployment Name"} />
+        <Table.Column dataIndex="clientName" title={"Client"} />
+        <Table.Column 
+          dataIndex="status" 
+          title={"Status"} 
+          render={(value) => {
+            let color = 'green';
+            if (value === 'pending') {
+              color = 'orange';
+            } else if (value === 'failed') {
+              color = 'red';
+            }
+            return <Tag color={color}>{value.toUpperCase()}</Tag>;
+          }}
+        />
+        <Table.Column dataIndex="version" title={"Version"} />
+        <Table.Column dataIndex="deploymentDate" title={"Deployed On"} />
         <Table.Column
           title={"Actions"}
           dataIndex="actions"
           render={(_, record: BaseRecord) => (
             <Space>
-              <EditButton hideText size="small" recordItemId={record.id} />
               <ShowButton hideText size="small" recordItemId={record.id} />
+              <EditButton hideText size="small" recordItemId={record.id} />
               <DeleteButton hideText size="small" recordItemId={record.id} />
             </Space>
           )}
@@ -32,4 +49,4 @@ export const CategoryList = () => {
       </Table>
     </List>
   );
-};
+};

+ 93 - 0
src/pages/deployments/show.tsx

@@ -0,0 +1,93 @@
+import { Show, TextField, TagField, DateField } from "@refinedev/antd";
+import { useOne, useShow } from "@refinedev/core";
+import { Typography, Card, Descriptions, Badge, Divider, Progress, Row, Col } from "antd";
+import { CheckCircleOutlined, WarningOutlined } from '@ant-design/icons';
+
+const { Title } = Typography;
+
+export const DeploymentShow = () => {
+  const { queryResult } = useShow({});
+  const { data, isLoading } = queryResult;
+  const record = data?.data;
+
+  const { data: clientData, isLoading: clientIsLoading } = useOne({
+    resource: "clients",
+    id: record?.clientId || "",
+    queryOptions: {
+      enabled: !!record,
+    },
+  });
+
+  const { data: templateData, isLoading: templateIsLoading } = useOne({
+    resource: "templates",
+    id: record?.templateId || "",
+    queryOptions: {
+      enabled: !!record,
+    },
+  });
+
+  return (
+    <Show isLoading={isLoading}>
+      <Title level={5}>Deployment Information</Title>
+      
+      <Card>
+        <Descriptions bordered column={2}>
+          <Descriptions.Item label="Deployment Name">{record?.name}</Descriptions.Item>
+          <Descriptions.Item label="Status">
+            <Badge 
+              status={record?.status === "active" ? "success" : record?.status === "pending" ? "processing" : "error"} 
+              text={record?.status} 
+            />
+          </Descriptions.Item>
+          <Descriptions.Item label="Client">
+            {clientIsLoading ? "Loading..." : clientData?.data?.name}
+          </Descriptions.Item>
+          <Descriptions.Item label="Template">
+            {templateIsLoading ? "Loading..." : templateData?.data?.name}
+          </Descriptions.Item>
+          <Descriptions.Item label="Version">{record?.version}</Descriptions.Item>
+          <Descriptions.Item label="Environment">{record?.environment}</Descriptions.Item>
+          <Descriptions.Item label="Deployed On">
+            <DateField value={record?.deploymentDate} format="YYYY-MM-DD HH:mm" />
+          </Descriptions.Item>
+          <Descriptions.Item label="Last Updated">
+            <DateField value={record?.updatedAt} format="YYYY-MM-DD HH:mm" />
+          </Descriptions.Item>
+        </Descriptions>
+      </Card>
+
+      <Divider />
+      
+      <Row gutter={24}>
+        <Col span={12}>
+          <Card title="Health Status">
+            <div style={{ display: 'flex', alignItems: 'center' }}>
+              {record?.healthStatus === "healthy" ? (
+                <CheckCircleOutlined style={{ color: 'green', fontSize: '24px', marginRight: '10px' }} />
+              ) : (
+                <WarningOutlined style={{ color: 'red', fontSize: '24px', marginRight: '10px' }} />
+              )}
+              <span style={{ fontSize: '16px' }}>
+                {record?.healthStatus === "healthy" ? "All systems operational" : "Issues detected"}
+              </span>
+            </div>
+          </Card>
+        </Col>
+        <Col span={12}>
+          <Card title="Resource Utilization">
+            <div>
+              <div style={{ marginBottom: '10px' }}>CPU</div>
+              <Progress percent={record?.cpuUsage || 0} size="small" />
+              
+              <div style={{ marginBottom: '10px', marginTop: '15px' }}>Memory</div>
+              <Progress percent={record?.memoryUsage || 0} size="small" />
+              
+              <div style={{ marginBottom: '10px', marginTop: '15px' }}>Storage</div>
+              <Progress percent={record?.storageUsage || 0} size="small" />
+            </div>
+          </Card>
+        </Col>
+      </Row>
+    </Show>
+  );
+};

+ 58 - 1
src/pages/forgotPassword/index.tsx

@@ -1,5 +1,62 @@
 import { AuthPage } from "@refinedev/antd";
+import { Typography, Alert, Space } from "antd";
+import { useState } from "react";
+import { useForgotPassword } from "@refinedev/core";
+
+const { Title, Text } = Typography;
 
 export const ForgotPassword = () => {
-  return <AuthPage type="forgotPassword" />;
+  const [error, setError] = useState<string | null>(null);
+  const [success, setSuccess] = useState<boolean>(false);
+  const { mutate: forgotPassword } = useForgotPassword();
+
+  const handleSubmit = async (values: any) => {
+    setError(null);
+    setSuccess(false);
+    
+    forgotPassword(values, {
+      onSuccess: () => {
+        setSuccess(true);
+      },
+      onError: (error) => {
+        setError(error?.message || "An error occurred. Please try again.");
+      }
+    });
+  };
+
+  return (
+    <AuthPage
+      type="forgotPassword"
+      title={
+        <Space direction="vertical" size={0} style={{ textAlign: "center" }}>
+          <Title level={3}>Forgot Password</Title>
+          <Text type="secondary">Enter your email to reset your password</Text>
+        </Space>
+      }
+      formProps={{
+        onFinish: handleSubmit,
+      }}
+      renderContent={(content: React.ReactNode) => (
+        <Space direction="vertical" style={{ width: "100%" }}>
+          {error && (
+            <Alert 
+              message="Error" 
+              description={error} 
+              type="error" 
+              showIcon 
+            />
+          )}
+          {success && (
+            <Alert 
+              message="Success" 
+              description="If your email is registered with us, you will receive password reset instructions." 
+              type="success" 
+              showIcon 
+            />
+          )}
+          {content}
+        </Space>
+      )}
+    />
+  );
 };

+ 38 - 1
src/pages/login/index.tsx

@@ -1,12 +1,49 @@
 import { AuthPage } from "@refinedev/antd";
+import { Typography, Alert, Space } from "antd";
+import { useState } from "react";
+import { useLogin } from "@refinedev/core";
+
+const { Title, Text } = Typography;
 
 export const Login = () => {
+  const [error, setError] = useState<string | null>(null);
+  const { mutate: login } = useLogin();
+
+  const handleSubmit = async (values: any) => {
+    setError(null);
+    
+    login(values, {
+      onError: (error) => {
+        setError(error?.message || "An error occurred during login");
+      }
+    });
+  };
+
   return (
     <AuthPage
       type="login"
+      title={
+        <Space direction="vertical" size={0} style={{ textAlign: "center" }}>
+          <Title level={3}>Welcome to BYOP Platform</Title>
+          <Text type="secondary">Login to manage your deployments</Text>
+        </Space>
+      }
       formProps={{
-        initialValues: { email: "demo@refine.dev", password: "demodemo" },
+        onFinish: handleSubmit,
       }}
+      renderContent={(content: React.ReactNode) => (
+        <Space direction="vertical" style={{ width: "100%" }}>
+          {error && (
+            <Alert 
+              message="Login Failed" 
+              description={error} 
+              type="error" 
+              showIcon 
+            />
+          )}
+          {content}
+        </Space>
+      )}
     />
   );
 };

+ 180 - 0
src/pages/monitoring/dashboard.tsx

@@ -0,0 +1,180 @@
+import { useList } from "@refinedev/core";
+import { Card, Col, Row, Statistic, Progress, Alert, Table, Typography } from "antd";
+import {
+  AreaChart,
+  Area,
+  XAxis,
+  YAxis,
+  CartesianGrid,
+  Tooltip,
+  ResponsiveContainer
+} from "recharts";
+import { 
+  CheckCircleOutlined, 
+  WarningOutlined, 
+  ArrowUpOutlined, 
+  ArrowDownOutlined 
+} from '@ant-design/icons';
+
+const { Title } = Typography;
+
+// Mock data for the chart
+const performanceData = [
+  { name: '00:00', cpu: 40, memory: 55, network: 20 },
+  { name: '03:00', cpu: 30, memory: 58, network: 28 },
+  { name: '06:00', cpu: 20, memory: 40, network: 20 },
+  { name: '09:00', cpu: 27, memory: 60, network: 40 },
+  { name: '12:00', cpu: 90, memory: 76, network: 60 },
+  { name: '15:00', cpu: 75, memory: 65, network: 50 },
+  { name: '18:00', cpu: 80, memory: 70, network: 45 },
+  { name: '21:00', cpu: 65, memory: 60, network: 30 },
+];
+
+// Mock data for alerts
+const alertsData = [
+  { id: 1, level: 'critical', message: 'Server CPU usage exceeds 90%', timestamp: '2025-05-08T12:30:00', status: 'active' },
+  { id: 2, level: 'warning', message: 'Database memory utilization above 75%', timestamp: '2025-05-08T11:15:00', status: 'active' },
+  { id: 3, level: 'info', message: 'Client deployment auto-scaled to 3 instances', timestamp: '2025-05-08T09:45:00', status: 'resolved' },
+  { id: 4, level: 'warning', message: 'Network latency spiked to 250ms', timestamp: '2025-05-08T08:20:00', status: 'resolved' },
+];
+
+export const MonitoringDashboard = () => {
+  const { data: deploymentsData } = useList({
+    resource: "deployments",
+  });
+
+  // Calculate some stats from deployments data
+  const activeDeployments = deploymentsData?.data?.filter(item => item.status === "active").length || 0;
+  const totalDeployments = deploymentsData?.data?.length || 0;
+  const healthyDeployments = deploymentsData?.data?.filter(item => item.healthStatus === "healthy").length || 0;
+
+  return (
+    <>
+      <Title level={4}>Infrastructure Monitoring</Title>
+      
+      <Row gutter={16} style={{ marginBottom: 24 }}>
+        <Col span={6}>
+          <Card>
+            <Statistic
+              title="Active Deployments"
+              value={activeDeployments}
+              precision={0}
+              valueStyle={{ color: '#3f8600' }}
+              prefix={<CheckCircleOutlined />}
+            />
+            <div style={{ marginTop: 10 }}>
+              <Progress percent={totalDeployments > 0 ? Math.round((activeDeployments / totalDeployments) * 100) : 0} size="small" />
+            </div>
+          </Card>
+        </Col>
+        <Col span={6}>
+          <Card>
+            <Statistic
+              title="Health Status"
+              value={`${healthyDeployments}/${totalDeployments}`}
+              valueStyle={{ color: healthyDeployments === totalDeployments ? '#3f8600' : '#faad14' }}
+              prefix={healthyDeployments === totalDeployments ? <CheckCircleOutlined /> : <WarningOutlined />}
+              suffix="deployments healthy"
+            />
+            <div style={{ marginTop: 10 }}>
+              <Progress percent={totalDeployments > 0 ? Math.round((healthyDeployments / totalDeployments) * 100) : 0} size="small" status={healthyDeployments === totalDeployments ? "success" : "exception"} />
+            </div>
+          </Card>
+        </Col>
+        <Col span={6}>
+          <Card>
+            <Statistic
+              title="Average CPU Usage"
+              value={68}
+              precision={0}
+              valueStyle={{ color: '#1890ff' }}
+              suffix="%"
+            />
+            <div style={{ marginTop: 10 }}>
+              <Progress percent={68} size="small" status={68 > 80 ? "exception" : "active"} />
+            </div>
+          </Card>
+        </Col>
+        <Col span={6}>
+          <Card>
+            <Statistic
+              title="Average Memory Usage"
+              value={72}
+              precision={0}
+              valueStyle={{ color: '#1890ff' }}
+              suffix="%"
+            />
+            <div style={{ marginTop: 10 }}>
+              <Progress percent={72} size="small" status={72 > 80 ? "exception" : "active"} />
+            </div>
+          </Card>
+        </Col>
+      </Row>
+
+      <Row gutter={16} style={{ marginBottom: 24 }}>
+        <Col span={16}>
+          <Card title="System Performance">
+            <ResponsiveContainer width="100%" height={300}>
+              <AreaChart
+                data={performanceData}
+                margin={{ top: 10, right: 30, left: 0, bottom: 0 }}
+              >
+                <CartesianGrid strokeDasharray="3 3" />
+                <XAxis dataKey="name" />
+                <YAxis />
+                <Tooltip />
+                <Area type="monotone" dataKey="cpu" stackId="1" stroke="#8884d8" fill="#8884d8" name="CPU %" />
+                <Area type="monotone" dataKey="memory" stackId="2" stroke="#82ca9d" fill="#82ca9d" name="Memory %" />
+                <Area type="monotone" dataKey="network" stackId="3" stroke="#ffc658" fill="#ffc658" name="Network MB/s" />
+              </AreaChart>
+            </ResponsiveContainer>
+          </Card>
+        </Col>
+        <Col span={8}>
+          <Card title="Active Alerts" style={{ height: '100%' }}>
+            {alertsData
+              .filter(alert => alert.status === 'active')
+              .map(alert => (
+                <Alert
+                  key={alert.id}
+                  message={alert.message}
+                  type={alert.level === 'critical' ? 'error' : alert.level === 'warning' ? 'warning' : 'info'}
+                  showIcon
+                  style={{ marginBottom: 10 }}
+                />
+              ))}
+          </Card>
+        </Col>
+      </Row>
+
+      <Row>
+        <Col span={24}>
+          <Card title="Recent System Events">
+            <Table 
+              dataSource={alertsData}
+              pagination={{ pageSize: 5 }}
+              rowKey="id"
+              columns={[
+                { title: 'Level', dataIndex: 'level', key: 'level', 
+                  render: (text) => {
+                    const color = text === 'critical' ? 'red' : text === 'warning' ? 'orange' : 'blue';
+                    return <span style={{ color }}>{text.toUpperCase()}</span>;
+                  }
+                },
+                { title: 'Message', dataIndex: 'message', key: 'message' },
+                { title: 'Timestamp', dataIndex: 'timestamp', key: 'timestamp' },
+                { title: 'Status', dataIndex: 'status', key: 'status',
+                  render: (text) => {
+                    return text === 'active' ? 
+                      <span style={{ color: 'red' }}>ACTIVE</span> : 
+                      <span style={{ color: 'green' }}>RESOLVED</span>;
+                  }
+                }
+              ]}
+            />
+          </Card>
+        </Col>
+      </Row>
+    </>
+  );
+};

+ 1 - 0
src/pages/monitoring/index.ts

@@ -0,0 +1 @@
+export * from "./dashboard";

+ 128 - 3
src/pages/register/index.tsx

@@ -1,5 +1,130 @@
-import { AuthPage } from "@refinedev/antd";
+import { Form, Input, Button, Typography, Alert, Card } from "antd";
+import { useState } from "react";
+import { useRegister, useLink } from "@refinedev/core";
+import { UserOutlined, MailOutlined, LockOutlined } from '@ant-design/icons';
+
+const { Title, Text } = Typography;
 
 export const Register = () => {
-  return <AuthPage type="register" />;
-};
+  const [error, setError] = useState<string | null>(null);
+  const { mutate: register } = useRegister();
+  const Link = useLink();
+  
+  const handleSubmit = (values: any) => {
+    setError(null);
+    console.log("Registration form data:", values);
+    
+    register(values, {
+      onSuccess: () => {
+        console.log("Registration successful");
+      },
+      onError: (error) => {
+        console.error("Registration error:", error);
+        setError(error?.message || "An error occurred during registration");
+      }
+    });
+  };
+
+  return (
+    <div style={{ 
+      display: "flex", 
+      flexDirection: "column",
+      alignItems: "center",
+      justifyContent: "center",
+      minHeight: "100vh",
+      background: "#f0f2f5" // Match the login page background
+    }}>
+      <Card
+        style={{
+          width: 400,
+          maxWidth: "90%",
+          padding: "24px 0",
+          boxShadow: "0 4px 12px rgba(0, 0, 0, 0.08)"
+        }}
+      >
+        <div style={{ textAlign: "center", marginBottom: 24 }}>
+          <Title level={3}>Join BYOP Platform</Title>
+          <Text type="secondary">Create an account to get started</Text>
+        </div>
+
+        {error && (
+          <Alert 
+            style={{ marginBottom: 24, marginLeft: 24, marginRight: 24 }}
+            message="Registration Failed" 
+            description={error} 
+            type="error" 
+            showIcon 
+          />
+        )}
+
+        <Form
+          name="register-form"
+          initialValues={{ username: "", email: "", password: "" }}
+          onFinish={handleSubmit}
+          layout="vertical"
+          style={{ padding: "0 24px" }}
+        >
+          <Form.Item
+            name="username"
+            label="Username"
+            rules={[{ required: true, message: 'Please input your username!' }]}
+          >
+            <Input 
+              prefix={<UserOutlined />} 
+              size="large" 
+              placeholder="Username" 
+            />
+          </Form.Item>
+
+          <Form.Item
+            name="email"
+            label="Email"
+            rules={[
+              { required: true, message: 'Please input your email!' },
+              { type: 'email', message: 'Please enter a valid email!' }
+            ]}
+          >
+            <Input 
+              prefix={<MailOutlined />} 
+              size="large" 
+              placeholder="Email" 
+            />
+          </Form.Item>
+
+          <Form.Item
+            name="password"
+            label="Password"
+            rules={[{ required: true, message: 'Please input your password!' }]}
+          >
+            <Input.Password 
+              prefix={<LockOutlined />} 
+              size="large" 
+              placeholder="Password" 
+              autoComplete="new-password"
+            />
+          </Form.Item>
+
+          <Form.Item>
+            <Button 
+              type="primary" 
+              htmlType="submit" 
+              size="large" 
+              block
+            >
+              Sign Up
+            </Button>
+          </Form.Item>
+          
+          <div style={{ textAlign: "center" }}>
+            <Text type="secondary">
+              Already have an account?{" "}
+              <Link to="/login">
+                Sign in
+              </Link>
+            </Text>
+          </div>
+        </Form>
+      </Card>
+    </div>
+  );
+};

+ 1 - 0
src/pages/support/index.ts

@@ -0,0 +1 @@
+export * from "./tickets";

+ 173 - 0
src/pages/support/tickets.tsx

@@ -0,0 +1,173 @@
+import {
+  List,
+  ShowButton,
+  useTable,
+  EditButton,
+  TagField,
+} from "@refinedev/antd";
+import type { BaseRecord } from "@refinedev/core";
+import { Space, Table, Tag, Badge, Typography, Input, Select, Button } from "antd";
+import { SearchOutlined, FilterOutlined } from '@ant-design/icons';
+import { useState } from "react";
+
+const { Title } = Typography;
+
+export const SupportTickets = () => {
+  const [searchText, setSearchText] = useState("");
+  const [priorityFilter, setPriorityFilter] = useState("all");
+  const [statusFilter, setStatusFilter] = useState("all");
+
+  const { tableProps } = useTable({
+    syncWithLocation: true,
+    filters: {
+      // Add server-side filters based on local state if API supports it
+    }
+  });
+
+  // Simulate client-side filtering for demo purposes
+  // In a real app, this would be done on server side
+  const filteredData = tableProps?.dataSource?.filter((ticket: any) => {
+    let matches = true;
+    
+    if (searchText) {
+      const searchLower = searchText.toLowerCase();
+      matches = matches && (
+        ticket?.title?.toLowerCase().includes(searchLower) || 
+        ticket?.description?.toLowerCase().includes(searchLower)
+      );
+    }
+    
+    if (priorityFilter !== "all") {
+      matches = matches && ticket?.priority === priorityFilter;
+    }
+    
+    if (statusFilter !== "all") {
+      matches = matches && ticket?.status === statusFilter;
+    }
+    
+    return matches;
+  });
+
+  const priorityColors = {
+    low: 'blue',
+    medium: 'orange',
+    high: 'red',
+    critical: 'purple'
+  };
+
+  const statusColors = {
+    open: 'green',
+    'in-progress': 'blue',
+    resolved: 'gray',
+    closed: 'black'
+  };
+
+  return (
+    <>
+      <Title level={4}>Support Tickets</Title>
+      
+      <div style={{ marginBottom: 16, display: 'flex', justifyContent: 'space-between' }}>
+        <Space>
+          <Input
+            placeholder="Search tickets"
+            prefix={<SearchOutlined />}
+            value={searchText}
+            onChange={(e) => setSearchText(e.target.value)}
+            style={{ width: 200 }}
+            allowClear
+          />
+          
+          <Select 
+            style={{ width: 120 }} 
+            defaultValue="all"
+            onChange={(value) => setPriorityFilter(value)} 
+            placeholder="Priority"
+          >
+            <Select.Option value="all">All Priorities</Select.Option>
+            <Select.Option value="low">Low</Select.Option>
+            <Select.Option value="medium">Medium</Select.Option>
+            <Select.Option value="high">High</Select.Option>
+            <Select.Option value="critical">Critical</Select.Option>
+          </Select>
+          
+          <Select 
+            style={{ width: 120 }} 
+            defaultValue="all"
+            onChange={(value) => setStatusFilter(value)} 
+            placeholder="Status"
+          >
+            <Select.Option value="all">All Statuses</Select.Option>
+            <Select.Option value="open">Open</Select.Option>
+            <Select.Option value="in-progress">In Progress</Select.Option>
+            <Select.Option value="resolved">Resolved</Select.Option>
+            <Select.Option value="closed">Closed</Select.Option>
+          </Select>
+        </Space>
+        
+        <Button type="primary">Create Ticket</Button>
+      </div>
+      
+      <List>
+        <Table 
+          {...tableProps} 
+          dataSource={filteredData || tableProps.dataSource} 
+          rowKey="id"
+          pagination={{ pageSize: 10 }}
+        >
+          <Table.Column dataIndex="id" title="Ticket ID" />
+          <Table.Column dataIndex="title" title="Title" />
+          <Table.Column 
+            dataIndex="clientName" 
+            title="Client" 
+            render={(value, record: any) => (
+              <span>
+                {value}
+                {record.clientId && <div style={{ fontSize: '12px', color: '#888' }}>ID: {record.clientId}</div>}
+              </span>
+            )}
+          />
+          <Table.Column 
+            dataIndex="priority" 
+            title="Priority" 
+            render={(value) => (
+              <Tag color={priorityColors[value as keyof typeof priorityColors] || 'default'}>
+                {value?.toUpperCase()}
+              </Tag>
+            )}
+          />
+          <Table.Column 
+            dataIndex="status" 
+            title="Status" 
+            render={(value) => (
+              <Badge 
+                color={statusColors[value as keyof typeof statusColors] || 'default'} 
+                text={value?.replace('-', ' ')} 
+              />
+            )}
+          />
+          <Table.Column 
+            dataIndex="category" 
+            title="Category" 
+            render={(value) => (
+              <TagField value={value} />
+            )}
+          />
+          <Table.Column dataIndex="createdAt" title="Created" />
+          <Table.Column
+            title="Actions"
+            dataIndex="actions"
+            render={(_, record: BaseRecord) => (
+              <Space>
+                <ShowButton hideText size="small" recordItemId={record.id} />
+                <EditButton hideText size="small" recordItemId={record.id} />
+                <Button type="primary" size="small">
+                  Respond
+                </Button>
+              </Space>
+            )}
+          />
+        </Table>
+      </List>
+    </>
+  );
+};

+ 535 - 0
src/pages/templates/create.tsx

@@ -0,0 +1,535 @@
+import { Create, useForm, useSelect } from "@refinedev/antd";
+import { Form, Input, Tabs, Card, Button, Select, InputNumber, Switch, Space, Divider } from "antd";
+import { useState } from "react";
+import { TemplateFormData, TemplateConfig, AppConfig, NetworkPolicy, SecretConfig } from "../../types/template";
+import { MinusCircleOutlined, PlusOutlined } from "@ant-design/icons";
+import { useApiUrl } from "@refinedev/core";
+
+const { TabPane } = Tabs;
+const { TextArea } = Input;
+
+export const TemplateCreate = () => {
+  const apiUrl = useApiUrl();
+  const { formProps, saveButtonProps } = useForm<TemplateFormData>({
+    redirect: "list",
+    onMutationSuccess: (data) => {
+      console.log("Template created successfully:", data);
+    },
+    meta: {
+      onSubmit: (values: { config: { apps: any[]; networkPolicies: any[]; }; }) => {
+        // Convert exposedPorts to integers for all apps
+        if (values.config.apps) {
+          values.config.apps = values.config.apps.map((app: { exposedPorts: any[]; }) => ({
+            ...app,
+            exposedPorts: app.exposedPorts?.map((port: string) => 
+              typeof port === 'string' ? parseInt(port, 10) : port
+            ),
+          }));
+        }
+
+        // Convert network policy ports to integers as well
+        if (values.config.networkPolicies) {
+          values.config.networkPolicies = values.config.networkPolicies.map((policy: { ports: any[]; }) => ({
+            ...policy,
+            ports: policy.ports?.map((port: string) => 
+              typeof port === 'string' ? parseInt(port, 10) : port
+            ),
+          }));
+        }
+        
+        return values;
+      },
+    },
+  });
+  
+  const [activeTabKey, setActiveTabKey] = useState("basic");
+  
+  // For app selection in the template
+  const { selectProps: appSelectProps } = useSelect({
+    resource: "apps",
+    optionLabel: "name",
+    optionValue: "id",
+  });
+
+  // Initialize with default values
+  const initialValues: Partial<TemplateFormData> = {
+    version: "1.0.0",
+    config: {
+      apps: [],
+      networkPolicies: [],
+      envVariables: {},
+      secrets: []
+    }
+  };
+
+  return (
+    <Create saveButtonProps={saveButtonProps}>
+      <Form 
+        {...formProps} 
+        layout="vertical" 
+        initialValues={initialValues}
+        onValuesChange={(_, allValues) => {
+          console.log("Form values:", allValues);
+        }}
+      >
+        <Tabs 
+          activeKey={activeTabKey} 
+          onChange={setActiveTabKey}
+        >
+          <TabPane tab="Basic Information" key="basic">
+            <Card title="Template Details" bordered={false}>
+              <Form.Item
+                label="Template Name"
+                name="name"
+                rules={[{ required: true, message: 'Please enter a template name' }]}
+              >
+                <Input placeholder="Enter template name" />
+              </Form.Item>
+
+              <Form.Item
+                label="Description"
+                name="description"
+                rules={[{ required: true, message: 'Please enter a description' }]}
+              >
+                <TextArea rows={3} placeholder="Describe this template" />
+              </Form.Item>
+
+              <Form.Item
+                label="Version"
+                name="version"
+                rules={[{ required: true, message: 'Please enter a version' }]}
+              >
+                <Input placeholder="1.0.0" />
+              </Form.Item>
+            </Card>
+          </TabPane>
+
+          <TabPane tab="Apps Configuration" key="apps">
+            <Card title="Configure Apps" bordered={false}>
+              <Form.List name={["config", "apps"]}>
+                {(fields, { add, remove }) => (
+                  <>
+                    {fields.map(({ key, name, ...restField }) => (
+                      <Card 
+                        key={key}
+                        title={`App ${name + 1}`}
+                        style={{ marginBottom: 16 }}
+                        extra={
+                          <Button 
+                            type="text" 
+                            onClick={() => remove(name)} 
+                            danger
+                            icon={<MinusCircleOutlined />}
+                          >
+                            Remove
+                          </Button>
+                        }
+                      >
+                        <Form.Item
+                          {...restField}
+                          name={[name, "id"]}
+                          label="App"
+                          rules={[{ required: true, message: 'Please select an app' }]}
+                        >
+                          <Select
+                            {...appSelectProps}
+                            placeholder="Select an app"
+                          />
+                        </Form.Item>
+
+                        <Form.Item
+                          {...restField}
+                          name={[name, "name"]}
+                          label="Display Name"
+                          rules={[{ required: true, message: 'Please enter a name for this app instance' }]}
+                        >
+                          <Input placeholder="Name for this app instance" />
+                        </Form.Item>
+
+                        <Form.Item
+                          {...restField}
+                          label="Exposed Ports"
+                          name={[name, "exposedPorts"]}
+                          getValueFromEvent={(values) => {
+                            return values.map((value: string | number) => 
+                              typeof value === 'string' ? parseInt(value, 10) : value
+                            );
+                          }}
+                        >
+                          <Select
+                            mode="tags"
+                            tokenSeparators={[',']}
+                            placeholder="Enter ports (e.g., 8080, 443)"
+                          />
+                        </Form.Item>
+
+                        <Form.Item
+                          {...restField}
+                          label="Public Access"
+                          name={[name, "publicAccess"]}
+                          valuePropName="checked"
+                          initialValue={false}
+                        >
+                          <Switch />
+                        </Form.Item>
+
+                        <Form.Item
+                          {...restField}
+                          label="Service Mesh"
+                          name={[name, "serviceMesh"]}
+                          valuePropName="checked"
+                          initialValue={false}
+                        >
+                          <Switch />
+                        </Form.Item>
+
+                        <Divider orientation="left">Resources</Divider>
+
+                        <Form.Item
+                          {...restField}
+                          name={[name, "resources", "cpu"]}
+                          label="CPU"
+                          rules={[{ required: true, message: 'Please specify CPU resources' }]}
+                          initialValue="0.5"
+                        >
+                          <Input placeholder="0.5" />
+                        </Form.Item>
+
+                        <Form.Item
+                          {...restField}
+                          name={[name, "resources", "memory"]}
+                          label="Memory"
+                          rules={[{ required: true, message: 'Please specify memory resources' }]}
+                          initialValue="512Mi"
+                        >
+                          <Input placeholder="512Mi" />
+                        </Form.Item>
+
+                        <Form.Item
+                          {...restField}
+                          name={[name, "resources", "storage"]}
+                          label="Storage"
+                          rules={[{ required: true, message: 'Please specify storage resources' }]}
+                          initialValue="1Gi"
+                        >
+                          <Input placeholder="1Gi" />
+                        </Form.Item>
+
+                        <Divider orientation="left">Autoscaling</Divider>
+
+                        <Form.Item
+                          {...restField}
+                          label="Enable Autoscaling"
+                          name={[name, "autoscaling", "enabled"]}
+                          valuePropName="checked"
+                          initialValue={false}
+                        >
+                          <Switch />
+                        </Form.Item>
+
+                        <Form.Item noStyle shouldUpdate={(prevValues, currentValues) => {
+                          return prevValues?.config?.apps?.[name]?.autoscaling?.enabled !== 
+                                 currentValues?.config?.apps?.[name]?.autoscaling?.enabled;
+                        }}>
+                          {({ getFieldValue }) => {
+                            const enabled = getFieldValue(['config', 'apps', name, 'autoscaling', 'enabled']);
+                            
+                            if (!enabled) {
+                              return null;
+                            }
+
+                            return (
+                              <>
+                                <Form.Item
+                                  {...restField}
+                                  name={[name, "autoscaling", "minReplicas"]}
+                                  label="Min Replicas"
+                                  initialValue={1}
+                                >
+                                  <InputNumber min={1} max={10} />
+                                </Form.Item>
+
+                                <Form.Item
+                                  {...restField}
+                                  name={[name, "autoscaling", "maxReplicas"]}
+                                  label="Max Replicas"
+                                  initialValue={3}
+                                >
+                                  <InputNumber min={1} max={20} />
+                                </Form.Item>
+
+                                <Form.Item
+                                  {...restField}
+                                  name={[name, "autoscaling", "cpuThreshold"]}
+                                  label="CPU Threshold (%)"
+                                  initialValue={80}
+                                >
+                                  <InputNumber min={1} max={100} />
+                                </Form.Item>
+
+                                <Form.Item
+                                  {...restField}
+                                  name={[name, "autoscaling", "metric"]}
+                                  label="Scaling Metric"
+                                  initialValue="cpu"
+                                >
+                                  <Select
+                                    options={[
+                                      { label: "CPU", value: "cpu" },
+                                      { label: "Memory", value: "memory" },
+                                      { label: "Requests", value: "requests" }
+                                    ]}
+                                  />
+                                </Form.Item>
+                              </>
+                            );
+                          }}
+                        </Form.Item>
+
+                        <Divider orientation="left">Environment Overrides</Divider>
+                        <Form.List name={[name, "envOverrides"]}>
+                          {(envFields, { add: addEnv, remove: removeEnv }) => (
+                            <>
+                              {envFields.map(({ key, name: envName, ...restEnvField }) => (
+                                <Space key={key} style={{ display: 'flex', marginBottom: 8 }} align="baseline">
+                                  <Form.Item
+                                    {...restEnvField}
+                                    name={[envName, "key"]}
+                                    rules={[{ required: true, message: 'Missing key' }]}
+                                  >
+                                    <Input placeholder="ENV_KEY" />
+                                  </Form.Item>
+                                  <Form.Item
+                                    {...restEnvField}
+                                    name={[envName, "value"]}
+                                    rules={[{ required: true, message: 'Missing value' }]}
+                                  >
+                                    <Input placeholder="value" />
+                                  </Form.Item>
+                                  <MinusCircleOutlined onClick={() => removeEnv(envName)} />
+                                </Space>
+                              ))}
+                              <Form.Item>
+                                <Button type="dashed" onClick={() => addEnv()} block icon={<PlusOutlined />}>
+                                  Add Environment Variable
+                                </Button>
+                              </Form.Item>
+                            </>
+                          )}
+                        </Form.List>
+                      </Card>
+                    ))}
+                    <Form.Item>
+                      <Button type="dashed" onClick={() => add()} block icon={<PlusOutlined />}>
+                        Add App
+                      </Button>
+                    </Form.Item>
+                  </>
+                )}
+              </Form.List>
+            </Card>
+          </TabPane>
+
+          <TabPane tab="Network Policies" key="network">
+            <Card title="Network Policies" bordered={false}>
+              <Form.List name={["config", "networkPolicies"]}>
+                {(fields, { add, remove }) => (
+                  <>
+                    {fields.map(({ key, name, ...restField }) => (
+                      <Card 
+                        key={key}
+                        title={`Policy ${name + 1}`}
+                        style={{ marginBottom: 16 }}
+                        extra={
+                          <Button 
+                            type="text" 
+                            onClick={() => remove(name)} 
+                            danger
+                            icon={<MinusCircleOutlined />}
+                          >
+                            Remove
+                          </Button>
+                        }
+                      >
+                        <Form.Item
+                          {...restField}
+                          name={[name, "name"]}
+                          label="Policy Name"
+                          rules={[{ required: true, message: 'Please enter a policy name' }]}
+                        >
+                          <Input placeholder="Enter policy name" />
+                        </Form.Item>
+
+                        <Form.Item
+                          {...restField}
+                          name={[name, "fromApps"]}
+                          label="Source Apps"
+                          rules={[{ required: true, message: 'Please select source apps' }]}
+                        >
+                          <Select
+                            mode="multiple"
+                            placeholder="Select source apps"
+                          >
+                            {formProps.form?.getFieldValue(['config', 'apps'])?.map((app: AppConfig) => (
+                              <Select.Option key={app.id} value={app.id}>
+                                {app.name}
+                              </Select.Option>
+                            ))}
+                          </Select>
+                        </Form.Item>
+
+                        <Form.Item
+                          {...restField}
+                          name={[name, "toApps"]}
+                          label="Destination Apps"
+                          rules={[{ required: true, message: 'Please select destination apps' }]}
+                        >
+                          <Select
+                            mode="multiple"
+                            placeholder="Select destination apps"
+                          >
+                            {formProps.form?.getFieldValue(['config', 'apps'])?.map((app: AppConfig) => (
+                              <Select.Option key={app.id} value={app.id}>
+                                {app.name}
+                              </Select.Option>
+                            ))}
+                          </Select>
+                        </Form.Item>
+
+                        <Form.Item
+                          {...restField}
+                          label="Allowed Ports"
+                          name={[name, "ports"]}
+                          getValueFromEvent={(values) => {
+                            return values.map((value: string | number) => 
+                              typeof value === 'string' ? parseInt(value, 10) : value
+                            );
+                          }}
+                        >
+                          <Select
+                            mode="tags"
+                            tokenSeparators={[',']}
+                            placeholder="Enter allowed ports (e.g., 8080, 443)"
+                          />
+                        </Form.Item>
+
+                        <Form.Item
+                          {...restField}
+                          label="Allow Egress"
+                          name={[name, "allowEgress"]}
+                          valuePropName="checked"
+                          initialValue={true}
+                        >
+                          <Switch />
+                        </Form.Item>
+                      </Card>
+                    ))}
+                    <Form.Item>
+                      <Button type="dashed" onClick={() => add()} block icon={<PlusOutlined />}>
+                        Add Network Policy
+                      </Button>
+                    </Form.Item>
+                  </>
+                )}
+              </Form.List>
+            </Card>
+          </TabPane>
+
+          <TabPane tab="Environment & Secrets" key="env-secrets">
+            <Card title="Global Environment Variables" bordered={false}>
+              <Form.List name={["config", "envVariables"]}>
+                {(fields, { add, remove }) => (
+                  <>
+                    {fields.map(({ key, name, ...restField }) => (
+                      <Space key={key} style={{ display: 'flex', marginBottom: 8 }} align="baseline">
+                        <Form.Item
+                          {...restField}
+                          name={[name, "key"]}
+                          rules={[{ required: true, message: 'Missing key' }]}
+                        >
+                          <Input placeholder="ENV_KEY" />
+                        </Form.Item>
+                        <Form.Item
+                          {...restField}
+                          name={[name, "value"]}
+                          rules={[{ required: true, message: 'Missing value' }]}
+                        >
+                          <Input placeholder="value" />
+                        </Form.Item>
+                        <MinusCircleOutlined onClick={() => remove(name)} />
+                      </Space>
+                    ))}
+                    <Form.Item>
+                      <Button type="dashed" onClick={() => add()} block icon={<PlusOutlined />}>
+                        Add Environment Variable
+                      </Button>
+                    </Form.Item>
+                  </>
+                )}
+              </Form.List>
+            </Card>
+
+            <Card title="Secrets Configuration" bordered={false} style={{ marginTop: 16 }}>
+              <Form.List name={["config", "secrets"]}>
+                {(fields, { add, remove }) => (
+                  <>
+                    {fields.map(({ key, name, ...restField }) => (
+                      <Card 
+                        key={key}
+                        title={`Secret ${name + 1}`}
+                        style={{ marginBottom: 16 }}
+                        size="small"
+                        extra={
+                          <Button 
+                            type="text" 
+                            onClick={() => remove(name)} 
+                            danger
+                            icon={<MinusCircleOutlined />}
+                          >
+                            Remove
+                          </Button>
+                        }
+                      >
+                        <Form.Item
+                          {...restField}
+                          name={[name, "name"]}
+                          label="Secret Name"
+                          rules={[{ required: true, message: 'Please enter a secret name' }]}
+                        >
+                          <Input placeholder="Enter secret name" />
+                        </Form.Item>
+
+                        <Form.Item
+                          {...restField}
+                          name={[name, "description"]}
+                          label="Description"
+                        >
+                          <Input placeholder="Describe this secret" />
+                        </Form.Item>
+
+                        <Form.Item
+                          {...restField}
+                          label="Required"
+                          name={[name, "required"]}
+                          valuePropName="checked"
+                          initialValue={true}
+                        >
+                          <Switch />
+                        </Form.Item>
+                      </Card>
+                    ))}
+                    <Form.Item>
+                      <Button type="dashed" onClick={() => add()} block icon={<PlusOutlined />}>
+                        Add Secret
+                      </Button>
+                    </Form.Item>
+                  </>
+                )}
+              </Form.List>
+            </Card>
+          </TabPane>
+        </Tabs>
+      </Form>
+    </Create>
+  );
+};

+ 3 - 0
src/pages/templates/index.ts

@@ -0,0 +1,3 @@
+export * from "./create";
+export * from "./list";
+export * from "./show";

+ 88 - 0
src/pages/templates/list.tsx

@@ -0,0 +1,88 @@
+import {
+  DeleteButton,
+  EditButton,
+  List,
+  ShowButton,
+  useTable,
+} from "@refinedev/antd";
+import type { BaseRecord } from "@refinedev/core";
+import { Space, Table, Tag, Button, Tooltip, Typography } from "antd";
+import { PlusOutlined, ApiOutlined, ForkOutlined, LockOutlined } from '@ant-design/icons';
+
+const { Title } = Typography;
+
+export const TemplateList = () => {
+  const { tableProps } = useTable({
+    syncWithLocation: true,
+  });
+
+  return (
+    <>
+      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 16 }}>
+        <Title level={4}>Deployment Templates</Title>
+        <Button type="primary" icon={<PlusOutlined />} href="/templates/create">
+          Create New Template
+        </Button>
+      </div>
+
+      <List>
+        <Table {...tableProps} rowKey="id">
+          <Table.Column dataIndex="id" title="ID" />
+          <Table.Column 
+            dataIndex="name" 
+            title="Template Name"
+            sorter={(a, b) => a.name.localeCompare(b.name)}
+          />
+          <Table.Column dataIndex="description" title="Description" />
+          <Table.Column 
+            title="App Count" 
+            render={(_, record: any) => (
+              record?.config?.apps?.length || 0
+            )}
+          />
+          <Table.Column 
+            title="Features" 
+            render={(_, record: any) => (
+              <Space>
+                {record?.config?.networkPolicies?.length > 0 && (
+                  <Tooltip title="Network Policies">
+                    <ForkOutlined style={{ color: '#1890ff' }} />
+                  </Tooltip>
+                )}
+                {record?.config?.envVariables && Object.keys(record.config.envVariables).length > 0 && (
+                  <Tooltip title="Environment Variables">
+                    <ApiOutlined style={{ color: '#52c41a' }} />
+                  </Tooltip>
+                )}
+                {record?.config?.secrets?.length > 0 && (
+                  <Tooltip title="Secret Configuration">
+                    <LockOutlined style={{ color: '#fa8c16' }} />
+                  </Tooltip>
+                )}
+              </Space>
+            )}
+          />
+          <Table.Column dataIndex="version" title="Version" />
+          <Table.Column 
+            dataIndex="createdBy" 
+            title="Created By" 
+            render={(value) => (
+              <span>{value || "System"}</span>
+            )}
+          />
+          <Table.Column
+            title="Actions"
+            dataIndex="actions"
+            render={(_, record: BaseRecord) => (
+              <Space>
+                <ShowButton hideText size="small" recordItemId={record.id} />
+                <EditButton hideText size="small" recordItemId={record.id} />
+                <DeleteButton hideText size="small" recordItemId={record.id} />
+              </Space>
+            )}
+          />
+        </Table>
+      </List>
+    </>
+  );
+};

+ 287 - 0
src/pages/templates/show.tsx

@@ -0,0 +1,287 @@
+import { Show } from "@refinedev/antd";
+import { useShow } from "@refinedev/core";
+import { 
+  Typography, Card, Descriptions, Tabs, Table, Tag, Badge, 
+  List, Space, Divider, Button, Row, Col, Tooltip 
+} from "antd";
+import { 
+  ApiOutlined, ForkOutlined, LockOutlined, 
+  GlobalOutlined, RocketOutlined, CheckCircleOutlined 
+} from '@ant-design/icons';
+
+const { Title, Text } = Typography;
+const { TabPane } = Tabs;
+
+export const TemplateShow = () => {
+  const { queryResult } = useShow();
+  const { data, isLoading } = queryResult;
+  const record = data?.data;
+
+  // Format environment variables for display
+  const formatEnvVars = (envVars: Record<string, string> = {}) => {
+    return Object.entries(envVars).map(([key, value]) => ({
+      key,
+      value,
+    }));
+  };
+
+  return (
+    <Show isLoading={isLoading}
+      headerButtons={
+        <>
+          <Button type="primary" icon={<RocketOutlined />}>Deploy with This Template</Button>
+          <Button>Edit Template</Button>
+        </>
+      }
+    >
+      <Title level={4}>{record?.name}</Title>
+      <Descriptions bordered column={2} style={{ marginBottom: 20 }}>
+        <Descriptions.Item label="Template ID">{record?.id}</Descriptions.Item>
+        <Descriptions.Item label="Version">{record?.version}</Descriptions.Item>
+        <Descriptions.Item label="Created By">{record?.createdBy || 'System'}</Descriptions.Item>
+        <Descriptions.Item label="Created At">{record?.createdAt}</Descriptions.Item>
+        <Descriptions.Item label="Last Updated">{record?.updatedAt}</Descriptions.Item>
+        <Descriptions.Item label="Active Deployments">{record?.deployments?.length || 0}</Descriptions.Item>
+        <Descriptions.Item label="Description" span={2}>
+          {record?.description}
+        </Descriptions.Item>
+      </Descriptions>
+
+      <Tabs defaultActiveKey="apps">
+        <TabPane tab={<span><ApiOutlined /> Apps Configuration</span>} key="apps">
+          <Table 
+            dataSource={record?.config?.apps || []}
+            rowKey="id"
+            pagination={false}
+            expandable={{
+              expandedRowRender: (app: {
+                  resources: any;
+                  autoscaling: any; envOverrides?: Record<string, string> 
+}) => (
+                <div style={{ padding: 16 }}>
+                  <Title level={5}>Resource Configuration</Title>
+                  <Descriptions bordered column={3} size="small">
+                    <Descriptions.Item label="CPU">{app.resources.cpu}</Descriptions.Item>
+                    <Descriptions.Item label="Memory">{app.resources.memory}</Descriptions.Item>
+                    <Descriptions.Item label="Storage">{app.resources.storage}</Descriptions.Item>
+                  </Descriptions>
+                  
+                  {app.autoscaling && app.autoscaling.enabled && (
+                    <>
+                      <Title level={5} style={{ marginTop: 16 }}>Autoscaling</Title>
+                      <Descriptions bordered column={2} size="small">
+                        <Descriptions.Item label="Min Replicas">{app.autoscaling.minReplicas}</Descriptions.Item>
+                        <Descriptions.Item label="Max Replicas">{app.autoscaling.maxReplicas}</Descriptions.Item>
+                        <Descriptions.Item label="CPU Threshold">{app.autoscaling.cpuThreshold}%</Descriptions.Item>
+                        <Descriptions.Item label="Scaling Metric">{app.autoscaling.metric}</Descriptions.Item>
+                      </Descriptions>
+                    </>
+                  )}
+
+                  {app.envOverrides && Object.keys(app.envOverrides).length > 0 && (
+                    <>
+                      <Title level={5} style={{ marginTop: 16 }}>Environment Overrides</Title>
+                      <Table 
+                        dataSource={Object.entries(app.envOverrides || {}).map(([key, value]) => ({ key, value }))}
+                        columns={[
+                          { title: 'Key', dataIndex: 'key' },
+                          { title: 'Value', dataIndex: 'value' }
+                        ]}
+                        size="small"
+                        pagination={false}
+                      />
+                    </>
+                  )}
+                </div>
+              )
+            }}
+            columns={[
+              { title: 'App ID', dataIndex: 'id' },
+              { title: 'Name', dataIndex: 'name' },
+              { 
+                title: 'Ports', 
+                dataIndex: 'exposedPorts',
+                render: (ports: number[]) => (
+                  <Space>
+                    {ports && ports.length > 0 ? ports.map((port) => (
+                      <Tag key={port} color="blue">{port}</Tag>
+                    )) : 'None'}
+                  </Space>
+                )
+              },
+              {
+                title: 'Public Access',
+                dataIndex: 'publicAccess',
+                render: (value: boolean) => (
+                  value ? <Badge status="success" text="Yes" /> : <Badge status="default" text="No" />
+                )
+              },
+              {
+                title: 'Service Mesh',
+                dataIndex: 'serviceMesh',
+                render: (value: boolean) => (
+                  value ? <Badge status="success" text="Yes" /> : <Badge status="default" text="No" />
+                )
+              },
+              {
+                title: 'Autoscaling',
+                dataIndex: 'autoscaling',
+                render: (autoscaling: any) => (
+                  autoscaling?.enabled ? 
+                    <Tooltip title={`${autoscaling.minReplicas}-${autoscaling.maxReplicas} instances`}>
+                      <Badge status="processing" text="Enabled" />
+                    </Tooltip> : 
+                    <Badge status="default" text="Disabled" />
+                )
+              }
+            ]}
+          />
+        </TabPane>
+
+        <TabPane tab={<span><ForkOutlined /> Network Policies</span>} key="network">
+          {record?.config?.networkPolicies?.length > 0 ? (
+            <List
+              itemLayout="vertical"
+              dataSource={record.config.networkPolicies}
+              renderItem={(policy) => (
+                <Card title={policy.name} style={{ marginBottom: 16 }}>
+                  <Row gutter={16}>
+                    <Col span={8}>
+                      <Title level={5}>Source Apps</Title>
+                      <List
+                        size="small"
+                        dataSource={policy.fromApps}
+                        renderItem={(appId) => {
+                          const app = record.config.apps.find(a => a.id === appId);
+                          return (
+                            <List.Item>
+                              {app ? app.name : appId}
+                            </List.Item>
+                          );
+                        }}
+                      />
+                    </Col>
+                    <Col span={8}>
+                      <Title level={5}>Destination Apps</Title>
+                      <List
+                        size="small"
+                        dataSource={policy.toApps}
+                        renderItem={(appId) => {
+                          const app = record.config.apps.find(a => a.id === appId);
+                          return (
+                            <List.Item>
+                              {app ? app.name : appId}
+                            </List.Item>
+                          );
+                        }}
+                      />
+                    </Col>
+                    <Col span={8}>
+                      <Title level={5}>Configuration</Title>
+                      <Descriptions column={1} size="small">
+                        <Descriptions.Item label="Allowed Ports">
+                          {policy.ports && policy.ports.length > 0 ? 
+                            policy.ports.map(port => <Tag key={port}>{port}</Tag>) : 
+                            'All Ports'}
+                        </Descriptions.Item>
+                        <Descriptions.Item label="Egress Traffic">
+                          {policy.allowEgress ? 
+                            <Badge status="success" text="Allowed" /> : 
+                            <Badge status="error" text="Blocked" />}
+                        </Descriptions.Item>
+                      </Descriptions>
+                    </Col>
+                  </Row>
+                </Card>
+              )}
+            />
+          ) : (
+            <Card>
+              <Text type="secondary">No network policies defined for this template.</Text>
+            </Card>
+          )}
+        </TabPane>
+
+        <TabPane tab={<span><GlobalOutlined /> Environment Variables</span>} key="env">
+          {record?.config?.envVariables && Object.keys(record.config.envVariables).length > 0 ? (
+            <Table 
+              dataSource={formatEnvVars(record.config.envVariables)}
+              columns={[
+                { title: 'Key', dataIndex: 'key' },
+                { title: 'Value', dataIndex: 'value' }
+              ]}
+              pagination={false}
+              rowKey="key"
+            />
+          ) : (
+            <Card>
+              <Text type="secondary">No global environment variables defined for this template.</Text>
+            </Card>
+          )}
+        </TabPane>
+
+        <TabPane tab={<span><LockOutlined /> Secrets</span>} key="secrets">
+          {record?.config?.secrets?.length > 0 ? (
+            <Table 
+              dataSource={record.config.secrets}
+              columns={[
+                { title: 'Name', dataIndex: 'name' },
+                { title: 'Description', dataIndex: 'description' },
+                { 
+                  title: 'Required', 
+                  dataIndex: 'required',
+                  render: (value: boolean) => value ? (
+                    <CheckCircleOutlined style={{ color: '#52c41a' }} />
+                  ) : (
+                    <Text type="secondary">Optional</Text>
+                  )
+                }
+              ]}
+              pagination={false}
+              rowKey="name"
+            />
+          ) : (
+            <Card>
+              <Text type="secondary">No secrets defined for this template.</Text>
+            </Card>
+          )}
+        </TabPane>
+
+        <TabPane tab="Deployments" key="deployments">
+          {record?.deployments?.length > 0 ? (
+            <Table
+              dataSource={record.deployments}
+              columns={[
+                { title: 'ID', dataIndex: 'id' },
+                { title: 'Name', dataIndex: 'name' },
+                { title: 'Client', dataIndex: 'clientName' },
+                { 
+                  title: 'Status', 
+                  dataIndex: 'status',
+                  render: (status) => {
+                    const colorMap: Record<string, string> = {
+                      active: 'green',
+                      pending: 'orange',
+                      failed: 'red',
+                      updating: 'blue',
+                      deleting: 'red'
+                    };
+                    
+                    return <Tag color={colorMap[status] || 'default'}>{status.toUpperCase()}</Tag>;
+                  }
+                },
+                { title: 'Created At', dataIndex: 'createdAt' }
+              ]}
+              pagination={false}
+              rowKey="id"
+            />
+          ) : (
+            <Card>
+              <Text type="secondary">No active deployments using this template.</Text>
+            </Card>
+          )}
+        </TabPane>
+      </Tabs>
+    </Show>
+  );
+};

+ 50 - 0
src/types/app.ts

@@ -0,0 +1,50 @@
+/**
+ * App data model that matches the UI components in the app section
+ */
+export interface App {
+  id: string;
+  name: string;
+  description: string;
+  type: AppType;
+  language: string;
+  version: string;
+  
+  // Configuration
+  configFile: string;
+  envVariables?: string;
+  
+  // Source code
+  repository?: string;
+  branch?: string;
+  buildCommand?: string;
+  
+  // Resources
+  resources?: string;
+  scaleSettings?: string;
+  
+  createdAt: string;
+  updatedAt: string;
+  createdBy: string;
+}
+
+export type AppType = 
+  | 'frontend'
+  | 'backend'
+  | 'api'
+  | 'database'
+  | 'microservice';
+
+export interface AppFormData {
+  name: string;
+  description: string;
+  type: AppType;
+  language: string;
+  version: string;
+  configFile: string;
+  envVariables?: string;
+  repository?: string;
+  branch?: string;
+  buildCommand?: string;
+  resources?: string;
+  scaleSettings?: string;
+}

+ 66 - 0
src/types/client.ts

@@ -0,0 +1,66 @@
+
+import { Deployment } from './deployment';
+/**
+ * Client data model that matches the backend API structure
+ */
+export interface Client {
+  id: string;
+  name: string;
+  contactEmail: string;
+  contactPhone?: string;
+  organization: string;
+  plan: PlanType;
+  createdAt: string;
+  updatedAt: string;
+  deletedAt?: string;
+  
+  // Relationships
+  deployments?: Deployment[];
+}
+
+export type PlanType = 'basic' | 'pro' | 'enterprise';
+
+export interface Address {
+  street: string;
+  city: string;
+  state: string;
+  postalCode: string;
+  country: string;
+}
+
+export interface Subscription {
+  plan: SubscriptionTier;
+  startDate: string;
+  renewalDate: string;
+  paymentStatus: PaymentStatus;
+  features: string[];
+  limits: ResourceLimits;
+}
+
+export type PaymentStatus = 
+  | 'active'
+  | 'pending'
+  | 'overdue'
+  | 'cancelled';
+
+export interface ResourceLimits {
+  maxDeployments: number;
+  maxApps: number;
+  maxCpuPerDeployment: string;
+  maxMemoryPerDeployment: string;
+  maxStorageTotal: string;
+  supportSLA: string;
+}
+
+export interface ClientFormData {
+  name: string;
+  contactEmail: string;
+  contactPhone?: string;
+  organization: string;
+  plan: PlanType;
+}
+
+export type SubscriptionTier = 
+  | 'basic'
+  | 'pro'
+  | 'enterprise';

+ 72 - 0
src/types/deployment.ts

@@ -0,0 +1,72 @@
+/**
+ * Deployment data model that matches the UI components in the deployments section
+ */
+export interface Deployment {
+  id: string;
+  name: string;
+  clientId: string;
+  clientName?: string;
+  templateId: string;
+  status: DeploymentStatus;
+  version: string;
+  environment: Environment;
+  containerCount: number;
+  
+  // Status & monitoring info
+  healthStatus?: HealthStatus;
+  cpuUsage?: number;
+  memoryUsage?: number;
+  storageUsage?: number;
+  
+  // Dates
+  deploymentDate: string;
+  updatedAt: string;
+  createdAt: string;
+  
+  // Relationships
+  deployedApps?: DeployedApp[];
+}
+
+export type DeploymentStatus = 
+  | 'pending'
+  | 'deploying'
+  | 'active'
+  | 'failed'
+  | 'updating'
+  | 'deleting';
+
+export type Environment = 
+  | 'development'
+  | 'staging'
+  | 'production';
+
+export type HealthStatus = 
+  | 'healthy'
+  | 'degraded'
+  | 'unhealthy';
+
+export interface DeployedApp {
+  appId: string;
+  status: AppDeploymentStatus;
+  version: string;
+  url?: string;
+  podCount?: number;
+  healthStatus?: HealthStatus;
+  configSnapshot: string;
+}
+
+export type AppDeploymentStatus = 
+  | 'pending'
+  | 'running'
+  | 'failed'
+  | 'scaling'
+  | 'updating';
+
+export interface DeploymentFormData {
+  name: string;
+  clientId: string;
+  templateId: string;
+  version: string;
+  containerCount: number;
+  environment: Environment;
+}

+ 83 - 0
src/types/template.ts

@@ -0,0 +1,83 @@
+/**
+ * Template data model that matches the Golang backend implementation
+ */
+export interface Template {
+  id: string;
+  name: string;
+  description: string;
+  version: string;
+  
+  // Configuration
+  config: TemplateConfig;
+  
+  // Metadata
+  createdAt: string;
+  updatedAt: string;
+  createdBy: string;
+  
+  // Relationships
+  deployments?: Deployment[];
+}
+
+export interface TemplateConfig {
+  apps: AppConfig[];
+  networkPolicies: NetworkPolicy[];
+  envVariables?: Record<string, string>;
+  secrets?: SecretConfig[];
+}
+
+export interface AppConfig {
+  id: string;
+  name: string;
+  exposedPorts?: number[];
+  publicAccess: boolean;
+  resources: ResourceConfig;
+  autoscaling?: AutoscalingConfig;
+  envOverrides?: Record<string, string>;
+  serviceMesh: boolean;
+}
+
+export interface ResourceConfig {
+  cpu: string;
+  memory: string;
+  storage: string;
+}
+
+export interface AutoscalingConfig {
+  enabled: boolean;
+  minReplicas: number;
+  maxReplicas: number;
+  cpuThreshold: number;
+  metric: string;
+}
+
+export interface NetworkPolicy {
+  name: string;
+  fromApps: string[];
+  toApps: string[];
+  ports?: number[];
+  allowEgress: boolean;
+}
+
+export interface SecretConfig {
+  name: string;
+  description: string;
+  required: boolean;
+}
+
+// For integration with existing components
+export interface Deployment {
+  id: string;
+  name: string;
+  // Additional fields omitted for brevity
+}
+
+/**
+ * Template form data for creating/editing templates
+ */
+export interface TemplateFormData {
+  name: string;
+  description: string;
+  version: string;
+  config: TemplateConfig;
+}

+ 59 - 0
src/types/user.ts

@@ -0,0 +1,59 @@
+/**
+ * User data model that matches authentication and permission requirements
+ * Note: Password is intentionally not included in this interface for security
+ */
+export interface User {
+  id: string;
+  username: string;
+  email: string;
+  role: UserRole;
+  clientId?: string; // Only present for client users
+  isActive: boolean;
+  lastLogin?: string;
+  preferences: UserPreferences;
+  permissions: Permission[];
+  
+  createdAt: string;
+  updatedAt: string;
+}
+
+export type UserRole = 
+  | 'system_admin'      // Full system access
+  | 'system_manager'    // Platform management but limited admin access
+  | 'support'           // Support staff
+  | 'developer'         // Internal developer
+  | 'client_manager'    // Limited to their own client resources
+  | 'client_user';      // Very limited permissions
+
+export interface Permission {
+  resource: string;
+  action: PermissionAction;
+  constraints?: Record<string, any>;
+}
+
+export type PermissionAction = 
+  | 'create'
+  | 'read'
+  | 'update'
+  | 'delete'
+  | 'deploy';
+
+export interface UserPreferences {
+  theme: string;
+  notifications: boolean;
+  dashboardLayout?: Record<string, any>;
+}
+
+/**
+ * User form data - what's accepted when creating/updating users
+ * Password only included in creation/password change operations
+ */
+export interface UserFormData {
+  username: string;
+  email: string;
+  role: UserRole;
+  clientId?: string;
+  isActive: boolean;
+  password?: string; // Only for creation/password reset
+  permissions?: Permission[];
+}