+
+ {Language.usedByLabel}
+
+
+ {template.workspace_owner_count}{" "}
+ {template.workspace_owner_count === 1 ? Language.userSingular : Language.userPlural}
+
+
+
+
+ {Language.activeVersionLabel}
+ {activeVersion.name}
+
+
+
+ {Language.lastUpdateLabel}
+
+ {dayjs().to(dayjs(template.updated_at))}
+
+
+
+ )
+}
+
+const useStyles = makeStyles((theme) => ({
+ stats: {
+ paddingLeft: theme.spacing(2),
+ paddingRight: theme.spacing(2),
+ backgroundColor: theme.palette.background.paper,
+ borderRadius: CardRadius,
+ display: "flex",
+ alignItems: "center",
+ color: theme.palette.text.secondary,
+ fontFamily: MONOSPACE_FONT_FAMILY,
+ border: `1px solid ${theme.palette.divider}`,
+ },
+
+ statItem: {
+ minWidth: theme.spacing(20),
+ padding: theme.spacing(2),
+ paddingTop: theme.spacing(1.75),
+ },
+
+ statsLabel: {
+ fontSize: 12,
+ textTransform: "uppercase",
+ display: "block",
+ fontWeight: 600,
+ },
+
+ statsValue: {
+ fontSize: 16,
+ marginTop: theme.spacing(0.25),
+ display: "inline-block",
+ },
+
+ statsDivider: {
+ width: 1,
+ height: theme.spacing(5),
+ backgroundColor: theme.palette.divider,
+ marginRight: theme.spacing(2),
+ },
+}))
diff --git a/site/src/hooks/useOrganizationId.ts b/site/src/hooks/useOrganizationId.ts
new file mode 100644
index 0000000000..93712a19da
--- /dev/null
+++ b/site/src/hooks/useOrganizationId.ts
@@ -0,0 +1,15 @@
+import { useSelector } from "@xstate/react"
+import { useContext } from "react"
+import { selectOrgId } from "../xServices/auth/authSelectors"
+import { XServiceContext } from "../xServices/StateContext"
+
+export const useOrganizationId = (): string => {
+ const xServices = useContext(XServiceContext)
+ const organizationId = useSelector(xServices.authXService, selectOrgId)
+
+ if (!organizationId) {
+ throw new Error("No organization ID found")
+ }
+
+ return organizationId
+}
diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx
index ae71dd5cf4..8bc1914a9c 100644
--- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx
+++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx
@@ -1,23 +1,11 @@
-import { useActor, useMachine } from "@xstate/react"
-import React, { useContext } from "react"
+import { useMachine } from "@xstate/react"
+import React from "react"
import { useNavigate, useSearchParams } from "react-router-dom"
import { Template } from "../../api/typesGenerated"
+import { useOrganizationId } from "../../hooks/useOrganizationId"
import { createWorkspaceMachine } from "../../xServices/createWorkspace/createWorkspaceXService"
-import { XServiceContext } from "../../xServices/StateContext"
import { CreateWorkspacePageView } from "./CreateWorkspacePageView"
-const useOrganizationId = () => {
- const xServices = useContext(XServiceContext)
- const [authState] = useActor(xServices.authXService)
- const organizationId = authState.context.me?.organization_ids[0]
-
- if (!organizationId) {
- throw new Error("No organization ID found")
- }
-
- return organizationId
-}
-
const CreateWorkspacePage: React.FC = () => {
const organizationId = useOrganizationId()
const [searchParams] = useSearchParams()
diff --git a/site/src/pages/TemplatePage/TemplatePage.test.tsx b/site/src/pages/TemplatePage/TemplatePage.test.tsx
new file mode 100644
index 0000000000..5c342f20e2
--- /dev/null
+++ b/site/src/pages/TemplatePage/TemplatePage.test.tsx
@@ -0,0 +1,13 @@
+import { screen } from "@testing-library/react"
+import React from "react"
+import { MockTemplate, MockWorkspaceResource, renderWithAuth } from "../../testHelpers/renderHelpers"
+import { TemplatePage } from "./TemplatePage"
+
+describe("TemplatePage", () => {
+ it("shows the template name, readme and resources", async () => {
+ renderWithAuth(