Skip to content

Commit a1cb8f2

Browse files
committed
optimize loading img in hero section
1 parent 9274545 commit a1cb8f2

File tree

8 files changed

+197
-21
lines changed

8 files changed

+197
-21
lines changed

index.html

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,67 @@
1818
href="https://api.fontshare.com/v2/css?f[]=clash-display@400,500,600,700&display=swap"
1919
rel="stylesheet"
2020
/>
21-
2221
<title>Pak Tani</title>
22+
23+
<style>
24+
body {
25+
margin: 0;
26+
font-family:
27+
-apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
28+
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
29+
sans-serif;
30+
background-color: #fff;
31+
}
32+
33+
.app-loader-container {
34+
display: flex;
35+
flex-direction: column;
36+
justify-content: center;
37+
align-items: center;
38+
height: 100vh;
39+
gap: 24px;
40+
}
41+
42+
.app-loader-container img {
43+
width: 80px;
44+
height: 80px;
45+
}
46+
47+
.app-loader-container p {
48+
font-size: 1.1rem;
49+
color: #4a4a4a;
50+
margin: 0;
51+
}
52+
53+
.arc-spinner {
54+
width: 24px;
55+
height: 24px;
56+
border-radius: 50%;
57+
58+
border: 4px solid transparent;
59+
border-top-color: #888;
60+
61+
animation: spin 1s linear infinite;
62+
}
63+
64+
@keyframes spin {
65+
0% {
66+
transform: rotate(0deg);
67+
}
68+
100% {
69+
transform: rotate(360deg);
70+
}
71+
}
72+
</style>
2373
</head>
2474
<body>
25-
<div id="root"></div>
75+
<div id="root">
76+
<div class="app-loader-container">
77+
<img src="/icon-smart-farming.png" alt="Logo Pak Tani" />
78+
<p>Dashboard Pak Tani sedang dimuat...</p>
79+
<div class="arc-spinner"></div>
80+
</div>
81+
</div>
2682
<script type="module" src="/src/index.jsx"></script>
2783
</body>
2884
</html>

package-lock.json

Lines changed: 18 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@
1414
"dependencies": {
1515
"@fontsource/rubik": "^5.2.8",
1616
"@tailwindcss/vite": "^4.1.13",
17+
"blurhash": "^2.0.5",
1718
"class-variance-authority": "^0.7.1",
1819
"clsx": "^2.1.1",
1920
"nprogress": "^0.2.0",
2021
"react": "^19.1.1",
2122
"react-aria-components": "^1.13.0",
23+
"react-blurhash": "^0.3.0",
2224
"react-dom": "^19.1.1",
2325
"react-icons": "^5.5.0",
2426
"react-router": "^7.9.1",

src/components/ui/button.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { forwardRef, cloneElement, isValidElement } from "react";
21
import { cva } from "class-variance-authority";
32
import { Button as AriaButton } from "react-aria-components";
3+
import { forwardRef, cloneElement, isValidElement } from "react";
44

55
import { cn } from "../../utils/cn";
66

src/features/core-app/components/core-app-header.jsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,10 @@ export const CoreAppHeader = () => {
6464

6565
{/* Navigasi Desktop */}
6666
<div className="hidden xl:flex items-center space-x-8">
67-
{CORE_APP_NAV_ITEMS.map((item, index) => (
67+
{CORE_APP_NAV_ITEMS.map((item) => (
6868
<Link
6969
to={item.href}
70-
key={index}
70+
key={`core-app-nav-item-${item.label}`}
7171
className={cn(
7272
"text-[20px]",
7373
getIsActivePath(item.href)
@@ -135,9 +135,9 @@ export const CoreAppHeader = () => {
135135
)}
136136
>
137137
<div className="flex flex-col items-center py-4">
138-
{CORE_APP_NAV_ITEMS.map((item, index) => (
138+
{CORE_APP_NAV_ITEMS.map((item) => (
139139
<Link
140-
key={index}
140+
key={`mobile-core-app-nav-item-${item.label}`}
141141
to={item.href}
142142
onClick={() => setIsMenuOpen(false)}
143143
className={cn(
Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,73 @@
1+
import { FaPlus } from "react-icons/fa6";
2+
import { FaSearch } from "react-icons/fa";
3+
4+
import { Button } from "../../components/ui/button";
5+
import { Input, TextField } from "../../components/ui/input";
6+
17
export const HistoryPage = () => {
2-
return <div>History page!</div>;
8+
return (
9+
<div className="app-container">
10+
<h1 className="clash-display-font font-semibold text-lg lg:text-[28px] tracking-wider mb-5">
11+
Mencatat aktivitas yang terjadi pada sistem
12+
</h1>
13+
14+
<div className="my-5">
15+
<h2 className="font-semibold text-lg lg:text-[20px] tracking-wider my-5">
16+
Cari Riwayat
17+
</h2>
18+
19+
<div className="grid grid-cols-12 gap-4 md:gap-2">
20+
{/* Input Pencarian */}
21+
<div className="col-span-12 lg:col-span-9 h-[54px]">
22+
<div className="relative h-full w-full">
23+
<FaSearch
24+
aria-hidden="true"
25+
className="
26+
absolute top-1/2 left-5 -translate-y-1/2
27+
text-zinc-500 pointer-events-none
28+
peer-focus:hidden transition-opacity
29+
"
30+
/>
31+
<TextField className="h-full">
32+
<Input
33+
type="text"
34+
placeholder="Search"
35+
className="rounded-[30px] h-full pl-12 peer"
36+
/>
37+
</TextField>
38+
</div>
39+
</div>
40+
41+
{/* Tombol Filter */}
42+
<Button
43+
variant="ghost"
44+
className="col-span-3 lg:col-span-1 bg-white hover:bg-white/70 size-[54px] aspect-square rounded-full mx-auto flex items-center justify-center"
45+
>
46+
<svg
47+
width={19}
48+
height={19}
49+
viewBox="0 0 19 19"
50+
fill="none"
51+
xmlns="http://www.w3.org/2000/svg"
52+
>
53+
<path
54+
d="M7.0875 1.18164C6.35435 1.18126 5.63914 1.40827 5.04042 1.83139C4.44169 2.25452 3.98894 2.85293 3.74456 3.54414H0V5.90664H3.74456C3.98861 6.5983 4.44119 7.19724 5.03992 7.62088C5.63865 8.04453 6.35405 8.27204 7.0875 8.27204C7.82095 8.27204 8.53635 8.04453 9.13508 7.62088C9.73381 7.19724 10.1864 6.5983 10.4304 5.90664H18.9V3.54414H10.4304C10.1861 2.85293 9.73331 2.25452 9.13458 1.83139C8.53586 1.40827 7.82064 1.18126 7.0875 1.18164ZM5.90625 4.72539C5.90625 4.4121 6.0307 4.11165 6.25223 3.89012C6.47376 3.66859 6.77421 3.54414 7.0875 3.54414C7.40079 3.54414 7.70124 3.66859 7.92277 3.89012C8.1443 4.11165 8.26875 4.4121 8.26875 4.72539C8.26875 5.03868 8.1443 5.33913 7.92277 5.56066C7.70124 5.78219 7.40079 5.90664 7.0875 5.90664C6.77421 5.90664 6.47376 5.78219 6.25223 5.56066C6.0307 5.33913 5.90625 5.03868 5.90625 4.72539ZM11.8125 10.6316C11.0794 10.6313 10.3641 10.8583 9.76542 11.2814C9.16669 11.7045 8.71394 12.3029 8.46956 12.9941H0V15.3566H8.46956C8.71361 16.0483 9.16619 16.6472 9.76492 17.0709C10.3636 17.4945 11.079 17.722 11.8125 17.722C12.546 17.722 13.2613 17.4945 13.8601 17.0709C14.4588 16.6472 14.9114 16.0483 15.1554 15.3566H18.9V12.9941H15.1554C14.9111 12.3029 14.4583 11.7045 13.8596 11.2814C13.2609 10.8583 12.5456 10.6313 11.8125 10.6316ZM10.6312 14.1754C10.6312 13.8621 10.7557 13.5616 10.9772 13.3401C11.1988 13.1186 11.4992 12.9941 11.8125 12.9941C12.1258 12.9941 12.4262 13.1186 12.6478 13.3401C12.8693 13.5616 12.9937 13.8621 12.9937 14.1754C12.9937 14.4887 12.8693 14.7891 12.6478 15.0107C12.4262 15.2322 12.1258 15.3566 11.8125 15.3566C11.4992 15.3566 11.1988 15.2322 10.9772 15.0107C10.7557 14.7891 10.6312 14.4887 10.6312 14.1754Z"
55+
className="fill-primary"
56+
/>
57+
</svg>
58+
</Button>
59+
60+
{/* Tombol Tambah Module */}
61+
<div className="col-span-9 lg:col-span-2">
62+
<Button
63+
className="h-[54px] w-full inline-flex text-base"
64+
variant="outline"
65+
>
66+
<FaPlus className="size-5 mr-4" /> Tambah Module
67+
</Button>
68+
</div>
69+
</div>
70+
</div>
71+
</div>
72+
);
373
};

src/pages/landing-page/home-page.jsx

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,54 @@ import backgroundImage from "../../assets/hero-image-bg.png";
33

44
import { Button } from "../../components/ui/button";
55
import { FEATURES } from "../../constants/landing-page-config.jsx";
6+
import { Blurhash } from "react-blurhash";
7+
import { useEffect, useState } from "react";
68

79
export const HomePage = () => {
10+
const [loaded, setLoaded] = useState(false);
11+
12+
const HERO_BLURHASH = "LlI#fGM{tQn~O[NJnPR,_4V[kVae";
13+
14+
useEffect(() => {
15+
const img = new Image();
16+
img.src = backgroundImage;
17+
img.onload = () => setLoaded(true);
18+
}, []);
19+
820
return (
921
<div>
1022
{/* Hero */}
11-
<div
12-
className="bg-surface h-[500px] md:h-[600px] lg:h-[712px] flex items-center"
13-
style={{
14-
backgroundImage: `url(${backgroundImage})`,
15-
backgroundSize: "cover",
16-
backgroundPosition: "center",
17-
}}
18-
>
19-
<div className="container mx-auto px-6 lg:px-[89px] pt-0 lg:pt-32">
23+
<div className="relative h-[500px] md:h-[600px] lg:h-[712px] flex items-center overflow-hidden">
24+
{/* Blurhash sebagai placeholder */}
25+
{!loaded && (
26+
<div className="absolute inset-0 w-full h-full">
27+
<Blurhash
28+
hash={HERO_BLURHASH}
29+
width={"100%"}
30+
height={"100%"}
31+
resolutionX={32}
32+
resolutionY={32}
33+
punch={1}
34+
/>
35+
</div>
36+
)}
37+
38+
{/* Background image utama */}
39+
<div
40+
className={`absolute inset-0 w-full h-full bg-center bg-cover transition-opacity duration-200 ${
41+
loaded ? "opacity-100" : "opacity-0"
42+
}`}
43+
style={{
44+
backgroundImage: `url(${backgroundImage})`,
45+
}}
46+
/>
47+
48+
{/* Konten hero */}
49+
<div className="container relative mx-auto px-6 lg:px-[89px] pt-0 lg:pt-32 z-10">
2050
<div className="max-w-full lg:max-w-[665px] text-center lg:text-left">
21-
{/* Penyesuaian font H1 */}
2251
<h1 className="text-4xl md:text-5xl lg:text-6xl font-semibold text-text-invers">
2352
Selamat Datang di Pak Tani!
2453
</h1>
25-
{/* Penyesuaian font Paragraf */}
2654
<p className="text-base md:text-lg lg:text-xl text-text-invers mt-2">
2755
Kelola dan pantau sistem irigasi pertanian Anda dengan mudah,
2856
langsung dari genggaman Anda.
@@ -55,9 +83,9 @@ export const HomePage = () => {
5583
</p>
5684
</div>
5785
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 mt-12 lg:mt-[61px] gap-8 lg:gap-[58px]">
58-
{FEATURES.map((feature, i) => (
86+
{FEATURES.map((feature) => (
5987
<div
60-
key={i}
88+
key={feature.title}
6189
className="bg-white w-full h-auto rounded-[20px] px-6 py-10 lg:px-[38px] lg:pt-[59px] shadow-md flex justify-center"
6290
>
6391
<div className="flex flex-col items-center gap-4 text-center">

src/styles/globals.css

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
body {
2828
@apply bg-background text-text;
2929

30+
min-width: 300px;
31+
3032
font-family: "Rubik", sans-serif;
3133
overflow-y: scroll;
3234
scrollbar-gutter: auto;

0 commit comments

Comments
 (0)