Skip to content

Commit 18ebd9f

Browse files
authored
♻️ Add EmptyState and Quickstart components (#245)
1 parent 27a61e3 commit 18ebd9f

File tree

5 files changed

+107
-35
lines changed

5 files changed

+107
-35
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { Button, Heading, Text } from "@chakra-ui/react"
2+
import { Link as RouterLink } from "@tanstack/react-router"
3+
import CustomCard from "./CustomCard"
4+
5+
interface EmptyStateProps {
6+
type: string
7+
}
8+
9+
const EmptyState = ({ type }: EmptyStateProps) => {
10+
return (
11+
<CustomCard
12+
w={{ base: "100%", md: "60%" }}
13+
display="flex"
14+
alignItems="center"
15+
justifyContent="center"
16+
flexDirection="column"
17+
gap="4"
18+
>
19+
<Heading size="sm" textAlign="center">
20+
You don't have any {type} yet
21+
</Heading>
22+
<Text>
23+
Create your first {type} to get started and deploy it to the cloud.
24+
</Text>
25+
<Button as={RouterLink} to="/$team/apps/new" variant="secondary">
26+
Create {`${type[0].toLocaleUpperCase()}${type.slice(1)}`}
27+
</Button>
28+
</CustomCard>
29+
)
30+
}
31+
32+
export default EmptyState
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { Code, Heading, Link, Text, VStack } from "@chakra-ui/react"
2+
import CustomCard from "./CustomCard"
3+
4+
const QuickStart = () => {
5+
return (
6+
<CustomCard w={{ base: "100%", md: "40%" }} data-testid="fastapi-cli">
7+
<VStack spacing={4} align="flex-start">
8+
<Heading size="sm">Quick Start with FastAPI CLI</Heading>
9+
<Text>
10+
FastAPI CLI is your primary tool for managing your apps. Before you
11+
start, make sure you have FastAPI CLI installed on your machine. You
12+
can install it using pip:
13+
</Text>
14+
<Text>
15+
<Code>pip install fastapi-cli</Code>
16+
</Text>
17+
<Heading size="sm">Getting started:</Heading>
18+
<Text>
19+
1. Initialize your app: <Code>fastapi init</Code>
20+
</Text>
21+
<Text>
22+
2. Deploy your app: <Code>fastapi deploy</Code>
23+
</Text>
24+
<Text>
25+
You can learn more in the{" "}
26+
<Link color="ui.main">FastAPI CLI documentation</Link>.
27+
</Text>
28+
</VStack>
29+
</CustomCard>
30+
)
31+
}
32+
33+
export default QuickStart

frontend/src/components/Common/SidebarItems.tsx

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,7 @@ import {
1616
type UseLinkPropsOptions,
1717
} from "@tanstack/react-router"
1818
import { CgOrganisation } from "react-icons/cg"
19-
import {
20-
FaCog,
21-
FaHome,
22-
FaLayerGroup
23-
} from "react-icons/fa"
19+
import { FaCog, FaHome, FaLayerGroup } from "react-icons/fa"
2420

2521
import { useCurrentUser } from "../../hooks/useAuth"
2622
import { Route } from "../../routes/_layout/$team"
@@ -73,7 +69,7 @@ const getSidebarItems = ({ team }: { team: string }): Array<Item> => {
7369
...link({
7470
to: "/teams/all",
7571
}),
76-
}
72+
},
7773
]
7874
}
7975

frontend/src/routes/_layout/$team/apps/index.tsx

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
TableContainer,
1111
Tbody,
1212
Td,
13+
Text,
1314
Th,
1415
Thead,
1516
Tr,
@@ -20,11 +21,13 @@ import {
2021
createFileRoute,
2122
useNavigate,
2223
} from "@tanstack/react-router"
23-
import { z } from "zod"
24-
2524
import { useEffect } from "react"
2625
import { ErrorBoundary } from "react-error-boundary"
26+
import { z } from "zod"
27+
2728
import { AppsService } from "../../../../client"
29+
import EmptyState from "../../../../components/Common/EmptyState"
30+
import QuickStart from "../../../../components/Common/QuickStart"
2831

2932
const appsSearchSchema = z.object({
3033
page: z.number().catch(1).optional(),
@@ -93,14 +96,22 @@ function Apps() {
9396

9497
return (
9598
<Container maxW="full">
96-
<Heading size="md" textAlign={{ base: "center", md: "left" }} mb={6}>
99+
<Heading size="md" textAlign={{ base: "center", md: "left" }} pb={2}>
97100
Apps
98101
</Heading>
99-
<Flex justifyContent="end">
100-
<Button as={RouterLink} to="/$team/apps/new" mb={4}>
101-
Create App
102-
</Button>
103-
</Flex>
102+
<Text>View and manage apps related to your team.</Text>
103+
{(apps?.data?.length ?? 0) > 0 && (
104+
<Flex justifyContent="end">
105+
<Button
106+
variant="secondary"
107+
as={RouterLink}
108+
to="/$team/apps/new"
109+
mb={4}
110+
>
111+
Create App
112+
</Button>
113+
</Flex>
114+
)}
104115
<ErrorBoundary
105116
fallbackRender={({ error }) => (
106117
<Box>Something went wrong: {error.message}</Box>
@@ -181,8 +192,10 @@ function Apps() {
181192
</Flex>
182193
</>
183194
) : (
184-
// TODO: Add new empty state component
185-
<Box>No apps found</Box>
195+
<Flex gap={4} pt={10} flexDir={{ base: "column", md: "row" }}>
196+
<EmptyState type="app" />
197+
<QuickStart />
198+
</Flex>
186199
)}
187200
</ErrorBoundary>
188201
</Container>

frontend/tests/apps.spec.ts

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,25 @@ import {
77
} from "./utils/random"
88
import { createTeam, logInUser, signUpNewUser } from "./utils/userUtils"
99

10-
// test.describe("Apps empty states", () => {
11-
// test("Empty state is visible when there are no apps", async ({ page }) => {
12-
// await page.goto("/admin/apps/")
13-
// await expect(page.getByText("You don't have any apps yet")).toBeVisible()
14-
// })
10+
test.describe("Apps empty states", () => {
11+
test("Empty state is visible when there are no apps", async ({ page }) => {
12+
await page.goto("/admin/apps/")
13+
await expect(
14+
page.getByRole("heading", { name: "You don't have any app yet" }),
15+
).toBeVisible()
16+
})
1517

16-
// test("FastAPI CLI instructions are visible", async ({ page, request }) => {
17-
// await page.goto("/admin/apps/")
18-
// await expect(page.getByTestId("fastapi-cli")).toBeVisible()
19-
// })
18+
test("FastAPI CLI instructions are visible", async ({ page, request }) => {
19+
await page.goto("/admin/apps/")
20+
await expect(page.getByTestId("fastapi-cli")).toBeVisible()
21+
})
2022

21-
// test("Create button is visible and navigates correctly", async ({ page }) => {
22-
// await page.goto("/admin/apps/")
23-
// await page
24-
// .locator("div")
25-
// .filter({ hasText: /^Create App$/ })
26-
// .nth(1)
27-
// .click()
28-
// await expect(page).toHaveURL("/admin/apps/new")
29-
// })
30-
// })
23+
test("Create button is visible and navigates correctly", async ({ page }) => {
24+
await page.goto("/admin/apps/")
25+
await page.getByRole('link', { name: 'Create App' }).click();
26+
await expect(page).toHaveURL('/admin/apps/new')
27+
})
28+
})
3129

3230
test.describe("User can manage apps succesfully", () => {
3331
test.use({ storageState: { cookies: [], origins: [] } })

0 commit comments

Comments
 (0)