Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 3529c74

Browse files
committed
Add filters
1 parent 79442ef commit 3529c74

File tree

1 file changed

+100
-15
lines changed

1 file changed

+100
-15
lines changed

site/src/pages/StarterTemplatesPage/StarterTemplatesPageView.tsx

Lines changed: 100 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { makeStyles } from "@material-ui/core/styles"
2+
import { TemplateExample } from "api/typesGenerated"
23
import { AlertBanner } from "components/AlertBanner/AlertBanner"
34
import { Maybe } from "components/Conditionals/Maybe"
45
import { Loader } from "components/Loader/Loader"
@@ -8,11 +9,42 @@ import {
89
PageHeaderSubtitle,
910
PageHeaderTitle,
1011
} from "components/PageHeader/PageHeader"
12+
import { Stack } from "components/Stack/Stack"
1113
import { FC } from "react"
1214
import { useTranslation } from "react-i18next"
1315
import { Link } from "react-router-dom"
1416
import { StarterTemplatesContext } from "xServices/starterTemplates/starterTemplatesXService"
1517

18+
const getTagLabel = (tag: string) => {
19+
const labelByTag: Record<string, string> = {
20+
digitalocean: "Digital Ocean",
21+
aws: "AWS",
22+
google: "Google Cloud",
23+
}
24+
25+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- this can be undefined
26+
return labelByTag[tag] ?? tag
27+
}
28+
29+
const getTemplatesByTag = (starterTemplates: TemplateExample[] | undefined) => {
30+
if (!starterTemplates) {
31+
return
32+
}
33+
34+
const tags: Record<string, TemplateExample[]> = {}
35+
starterTemplates.forEach((template) => {
36+
template.tags.forEach((tag) => {
37+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- this can be undefined
38+
if (tags[tag]) {
39+
tags[tag].push(template)
40+
} else {
41+
tags[tag] = [template]
42+
}
43+
})
44+
})
45+
return tags
46+
}
47+
1648
export interface StarterTemplatesPageViewProps {
1749
context: StarterTemplatesContext
1850
}
@@ -22,6 +54,10 @@ export const StarterTemplatesPageView: FC<StarterTemplatesPageViewProps> = ({
2254
}) => {
2355
const { t } = useTranslation("starterTemplatesPage")
2456
const styles = useStyles()
57+
const templatesByTag = getTemplatesByTag(context.starterTemplates)
58+
const tags = templatesByTag
59+
? Object.keys(templatesByTag).sort((a, b) => a.localeCompare(b))
60+
: undefined
2561

2662
return (
2763
<Margins>
@@ -38,27 +74,70 @@ export const StarterTemplatesPageView: FC<StarterTemplatesPageViewProps> = ({
3874
<Loader />
3975
</Maybe>
4076

41-
<div className={styles.templates}>
42-
{context.starterTemplates &&
43-
context.starterTemplates.map((example) => (
44-
<Link to={example.id} className={styles.template} key={example.id}>
45-
<div className={styles.templateIcon}>
46-
<img src={example.icon} alt="" />
47-
</div>
48-
<div className={styles.templateInfo}>
49-
<span className={styles.templateName}>{example.name}</span>
50-
<span className={styles.templateDescription}>
51-
{example.description}
52-
</span>
53-
</div>
77+
<Stack direction="row" spacing={4}>
78+
{templatesByTag && tags && (
79+
<Stack className={styles.filter}>
80+
<span className={styles.filterCaption}>Filter</span>
81+
<Link to="" className={styles.tagLink}>
82+
All templates ({context.starterTemplates?.length})
5483
</Link>
55-
))}
56-
</div>
84+
{tags.map((tag) => (
85+
<Link key={tag} to={`?tag=${tag}`} className={styles.tagLink}>
86+
{getTagLabel(tag)} ({templatesByTag[tag].length})
87+
</Link>
88+
))}
89+
</Stack>
90+
)}
91+
92+
<div className={styles.templates}>
93+
{context.starterTemplates &&
94+
context.starterTemplates.map((example) => (
95+
<Link
96+
to={example.id}
97+
className={styles.template}
98+
key={example.id}
99+
>
100+
<div className={styles.templateIcon}>
101+
<img src={example.icon} alt="" />
102+
</div>
103+
<div className={styles.templateInfo}>
104+
<span className={styles.templateName}>{example.name}</span>
105+
<span className={styles.templateDescription}>
106+
{example.description}
107+
</span>
108+
</div>
109+
</Link>
110+
))}
111+
</div>
112+
</Stack>
57113
</Margins>
58114
)
59115
}
60116

61117
const useStyles = makeStyles((theme) => ({
118+
filter: {
119+
width: theme.spacing(26),
120+
},
121+
122+
filterCaption: {
123+
textTransform: "uppercase",
124+
fontWeight: 600,
125+
fontSize: 12,
126+
color: theme.palette.text.secondary,
127+
letterSpacing: "0.1em",
128+
},
129+
130+
tagLink: {
131+
color: theme.palette.text.secondary,
132+
textDecoration: "none",
133+
fontSize: 14,
134+
textTransform: "capitalize",
135+
136+
"&:hover": {
137+
color: theme.palette.text.primary,
138+
},
139+
},
140+
62141
templates: {
63142
display: "grid",
64143
gridTemplateColumns: "repeat(2, minmax(0, 1fr))",
@@ -85,6 +164,7 @@ const useStyles = makeStyles((theme) => ({
85164
display: "flex",
86165
alignItems: "center",
87166
justifyContent: "center",
167+
flexShrink: 0,
88168

89169
"& img": {
90170
height: theme.spacing(4),
@@ -96,6 +176,7 @@ const useStyles = makeStyles((theme) => ({
96176
display: "flex",
97177
flexDirection: "column",
98178
gap: theme.spacing(0.5),
179+
overflow: "hidden",
99180
},
100181

101182
templateName: {
@@ -105,5 +186,9 @@ const useStyles = makeStyles((theme) => ({
105186
templateDescription: {
106187
fontSize: theme.spacing(1.75),
107188
color: theme.palette.text.secondary,
189+
textOverflow: "ellipsis",
190+
width: "100%",
191+
overflow: "hidden",
192+
whiteSpace: "nowrap",
108193
},
109194
}))

0 commit comments

Comments
 (0)