Skip to content

Commit db15310

Browse files
committed
Add flutter page
1 parent 6b95acc commit db15310

File tree

1 file changed

+170
-0
lines changed

1 file changed

+170
-0
lines changed

src/app/flutter/page.tsx

+170
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
"use client";
2+
3+
import {
4+
Box,
5+
Button,
6+
Card,
7+
CardSection,
8+
Container,
9+
Grid,
10+
GridCol,
11+
Group,
12+
Space,
13+
Text,
14+
TextInput,
15+
Title,
16+
} from "@mantine/core";
17+
import SiteFooter from "@/_components/footer/Footer";
18+
import { IconArrowUpRight, IconLink } from "@tabler/icons-react";
19+
import Days from "@/data/100days.json";
20+
import { useEffect, useState } from "react";
21+
import { useDebouncedCallback } from "@mantine/hooks";
22+
23+
interface exampleType {
24+
name: string;
25+
summery: string;
26+
repository: string;
27+
video: string;
28+
tags: string[];
29+
}
30+
31+
export default function AboutMe() {
32+
const [originalData, setOriginalData] = useState<exampleType[]>(
33+
Days.data.reverse()
34+
);
35+
const [search, setSearch] = useState("");
36+
const [visibleCount, setVisibleCount] = useState(0);
37+
const [perPage, setPerPage] = useState(9);
38+
const [examples, setExamples] = useState<exampleType[]>([]);
39+
40+
useEffect(() => {
41+
setExamples(originalData.slice(visibleCount, perPage));
42+
setVisibleCount(perPage);
43+
}, []);
44+
45+
const handleSearch = useDebouncedCallback(async (query: string) => {
46+
if (query.length) {
47+
let data = originalData.filter((day) => {
48+
return day.name.toLowerCase().includes(query.toLowerCase());
49+
});
50+
51+
setExamples(data);
52+
} else {
53+
setExamples(originalData.slice(0, perPage));
54+
}
55+
}, 500);
56+
57+
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
58+
setSearch(event.currentTarget.value);
59+
handleSearch(event.currentTarget.value);
60+
};
61+
62+
const loadMore = () => {
63+
setExamples((prev) => [
64+
...prev,
65+
...originalData.slice(visibleCount, visibleCount + perPage),
66+
]);
67+
setVisibleCount(visibleCount + perPage);
68+
};
69+
70+
return (
71+
<>
72+
<Container size="xl" pos="relative">
73+
<Box
74+
px={32}
75+
py={58}
76+
mt={40}
77+
style={{
78+
overflow: "hidden",
79+
position: "relative",
80+
borderRadius: 16,
81+
background:
82+
"light-dark(var(--mantine-color-gray-2), var(--mantine-color-dark-6))",
83+
}}
84+
>
85+
<Title
86+
order={1}
87+
fz={36}
88+
fw={600}
89+
ta="center"
90+
c={"light-dark(var(--mantine-color-dark-9), white)"}
91+
>
92+
Discover the Most Trending Flutter UI Designs
93+
</Title>
94+
<Text ta="center" mt={16} c="gray">
95+
Search in 100+ flutter UI design examples
96+
</Text>
97+
<Space h={40} />
98+
<Container size="sm">
99+
<TextInput
100+
radius="xl"
101+
size="lg"
102+
fz={14}
103+
placeholder="Search e.g e-commerce, login, state management, day 28"
104+
value={search}
105+
onChange={handleChange}
106+
/>
107+
</Container>
108+
</Box>
109+
<Space h={40} />
110+
<Grid>
111+
{examples.map((day) => {
112+
return (
113+
<GridCol span={4}>
114+
<Card radius="md" withBorder style={{ overflow: "hidden" }}>
115+
<CardSection>
116+
<Box>
117+
<iframe
118+
width="100%"
119+
height="300"
120+
src={day.video.replace("youtu.be", "youtube.com/embed")}
121+
title="YouTube video player"
122+
frameBorder={0}
123+
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
124+
></iframe>
125+
</Box>
126+
</CardSection>
127+
<Text fw={600} mt={16} fz={14} c="light-dark(black, white)">
128+
{day.name}
129+
</Text>
130+
<Text mt={8} c="gray" fz={13} truncate>
131+
{day.summery}
132+
</Text>
133+
134+
<Button
135+
variant="light"
136+
radius="xl"
137+
mt={32}
138+
leftSection={<IconLink size={18} />}
139+
component="a"
140+
href={day.repository}
141+
target="_blank"
142+
>
143+
source code
144+
</Button>
145+
</Card>
146+
</GridCol>
147+
);
148+
})}
149+
</Grid>
150+
<Space h={80} />
151+
{examples.length && !search.length ? (
152+
<Group justify="center">
153+
<Button
154+
w={200}
155+
size="lg"
156+
fz={14}
157+
variant="default"
158+
radius="xl"
159+
onClick={() => loadMore()}
160+
>
161+
Load More
162+
</Button>
163+
</Group>
164+
) : null}
165+
</Container>
166+
<Space h={150} />
167+
<SiteFooter />
168+
</>
169+
);
170+
}

0 commit comments

Comments
 (0)