diff --git a/package-lock.json b/package-lock.json index fd13154..8e9db41 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,7 @@ "react-facebook": "^9.0.12", "react-icons": "^5.5.0", "react-lazy-load-image-component": "^1.6.3", + "react-social-media-embed": "^2.5.18", "react-social-plugins": "^2.1.0", "snippet": "^0.1.0" }, @@ -1911,6 +1912,12 @@ "@types/react": "^19.0.0" } }, + "node_modules/@types/youtube-player": { + "version": "5.5.11", + "resolved": "https://registry.npmjs.org/@types/youtube-player/-/youtube-player-5.5.11.tgz", + "integrity": "sha512-pM41CDBqJqBmTeJWnF7NOGz82IQoYOhqzMYXv5vKCXBqGiYSLldxMtpCk6KAEtADTy49S45AriYaCaZyeUX38Q==", + "license": "MIT" + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.26.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.26.1.tgz", @@ -3683,6 +3690,12 @@ "node": ">= 6" } }, + "node_modules/classnames": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==", + "license": "MIT" + }, "node_modules/cli-table": { "version": "0.3.11", "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.11.tgz", @@ -4201,7 +4214,6 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, "license": "MIT" }, "node_modules/fast-glob": { @@ -4975,6 +4987,12 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "license": "MIT" }, + "node_modules/load-script": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/load-script/-/load-script-1.0.0.tgz", + "integrity": "sha512-kPEjMFtZvwL9TaZo0uZ2ml+Ye9HUMmPwbYRJ324qF9tqMejwykJ5ggTyvzmrbBeapCAbk98BSbTeovHEEP1uCA==", + "license": "MIT" + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -5695,6 +5713,16 @@ "react": ">= 16" } }, + "node_modules/react-html-props": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/react-html-props/-/react-html-props-2.1.1.tgz", + "integrity": "sha512-tM+YCYlr90m3JontKUAa+gNVU2zkyprlCS7OQ9aa3z2MfyJjAioJzrSmi1Vef/+UCTE6CQlPqLX4ebdLIJDKxw==", + "license": "MIT", + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 || ^22.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 || ^22.0.0" + } + }, "node_modules/react-icons": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz", @@ -5733,6 +5761,40 @@ "node": ">=0.10.0" } }, + "node_modules/react-social-media-embed": { + "version": "2.5.18", + "resolved": "https://registry.npmjs.org/react-social-media-embed/-/react-social-media-embed-2.5.18.tgz", + "integrity": "sha512-+PkzLRGAwnySkxKajaiK5VD+EjOhlFsh/vjNxgHsDfKBTseDpFxPrMXXQWkk6BRCwFBNVWX+V1HZ9AU0y54Wgw==", + "license": "MIT", + "dependencies": { + "@types/youtube-player": "^5.5.5", + "classnames": "^2.5.1", + "react-html-props": "^2.0.3", + "react-sub-unsub": "^2.2.1", + "react-twitter-embed": "^4.0.4", + "react-youtube": "^10.1.0" + }, + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 || ^22.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 || ^22.0.0" + } + }, + "node_modules/react-social-media-embed/node_modules/react-twitter-embed": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/react-twitter-embed/-/react-twitter-embed-4.0.4.tgz", + "integrity": "sha512-2JIL7qF+U62zRzpsh6SZDXNI3hRNVYf5vOZ1WRcMvwKouw+xC00PuFaD0aEp2wlyGaZ+f4x2VvX+uDadFQ3HVA==", + "license": "MIT", + "dependencies": { + "scriptjs": "^2.5.9" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-social-plugins": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/react-social-plugins/-/react-social-plugins-2.1.0.tgz", @@ -5757,6 +5819,33 @@ "node": ">=0.10.0" } }, + "node_modules/react-sub-unsub": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/react-sub-unsub/-/react-sub-unsub-2.2.8.tgz", + "integrity": "sha512-o3tmiOOZPdQUCmRhkdCHXRFLOHnCwdz/N3QZ1JQ14fQGA2HysKMF0kWu56ERnQUCK7wYVCQzI8pFbnivAYNQ+A==", + "license": "MIT", + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 || ^22.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 || ^22.0.0" + } + }, + "node_modules/react-youtube": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/react-youtube/-/react-youtube-10.1.0.tgz", + "integrity": "sha512-ZfGtcVpk0SSZtWCSTYOQKhfx5/1cfyEW1JN/mugGNfAxT3rmVJeMbGpA9+e78yG21ls5nc/5uZJETE3cm3knBg==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "3.1.3", + "prop-types": "15.8.1", + "youtube-player": "5.5.2" + }, + "engines": { + "node": ">= 14.x" + }, + "peerDependencies": { + "react": ">=0.14.1" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -5895,6 +5984,12 @@ "integrity": "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==", "license": "MIT" }, + "node_modules/scriptjs": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/scriptjs/-/scriptjs-2.5.9.tgz", + "integrity": "sha512-qGVDoreyYiP1pkQnbnFAUIS5AjenNwwQBdl7zeos9etl+hYKWahjRTfzAZZYBv5xNHx7vNKCmaLDQZ6Fr2AEXg==", + "license": "MIT" + }, "node_modules/scule": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/scule/-/scule-1.3.0.tgz", @@ -6000,6 +6095,12 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/sister": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/sister/-/sister-3.0.2.tgz", + "integrity": "sha512-p19rtTs+NksBRKW9qn0UhZ8/TUI9BPw9lmtHny+Y3TinWlOa9jWh9xB0AtPSdmOy49NJJJSSe0Ey4C7h0TrcYA==", + "license": "BSD-3-Clause" + }, "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -6804,6 +6905,32 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/youtube-player": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/youtube-player/-/youtube-player-5.5.2.tgz", + "integrity": "sha512-ZGtsemSpXnDky2AUYWgxjaopgB+shFHgXVpiJFeNB5nWEugpW1KWYDaHKuLqh2b67r24GtP6HoSW5swvf0fFIQ==", + "license": "BSD-3-Clause", + "dependencies": { + "debug": "^2.6.6", + "load-script": "^1.0.0", + "sister": "^3.0.0" + } + }, + "node_modules/youtube-player/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/youtube-player/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, "node_modules/zod": { "version": "3.24.2", "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.2.tgz", diff --git a/package.json b/package.json index 22c073e..4963628 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "react-facebook": "^9.0.12", "react-icons": "^5.5.0", "react-lazy-load-image-component": "^1.6.3", + "react-social-media-embed": "^2.5.18", "react-social-plugins": "^2.1.0", "snippet": "^0.1.0" }, diff --git a/public/images/new/recipe_title.webp b/public/images/new/recipe_title.webp new file mode 100644 index 0000000..04513e1 Binary files /dev/null and b/public/images/new/recipe_title.webp differ diff --git a/src/components/header.tsx b/src/components/header.tsx index 31ae080..7abf5c3 100644 --- a/src/components/header.tsx +++ b/src/components/header.tsx @@ -1,4 +1,4 @@ -import { Box, Flex, Image, VStack, Text } from '@chakra-ui/react'; +import { Box, Flex, Image, VStack, Text, Stack, Link } from '@chakra-ui/react'; import { GiHamburgerMenu } from "react-icons/gi"; import { IoCloseSharp } from "react-icons/io5"; import { colors } from '../colors'; @@ -52,18 +52,18 @@ function Header({ showMenu = false }: HeaderProps) { useEffect(() => { const handleScroll = () => { const currentScrollY = window.scrollY; - + if (currentScrollY > lastScrollY.current && currentScrollY > 100) { setIsVisible(false); } else { setIsVisible(true); } - + lastScrollY.current = currentScrollY; }; window.addEventListener('scroll', handleScroll, { passive: true }); - + return () => { window.removeEventListener('scroll', handleScroll); }; @@ -86,10 +86,10 @@ function Header({ showMenu = false }: HeaderProps) { return ( <> - ) : ( - @@ -149,22 +149,42 @@ function Header({ showMenu = false }: HeaderProps) { padding={0} margin={0} > - + {menuItems.map((item, index) => ( scrollToSection(item.id)} p={3} - borderRadius="md" - _hover={{ bg: 'gray.100' }} + _hover={{ bg: '#458B02' }} cursor="pointer" > - + {item.label} ))} + + + salespoint + + + + diff --git a/src/components/header2.tsx b/src/components/header2.tsx new file mode 100644 index 0000000..feb69d4 --- /dev/null +++ b/src/components/header2.tsx @@ -0,0 +1,14 @@ +import { Box, Flex, Image, } from '@chakra-ui/react'; +import { colors } from '../colors'; + +function Header2() { + return ( + + + Logo + + + ); +} + +export default Header2; \ No newline at end of file diff --git a/src/components/new_ui/truth.tsx b/src/components/new_ui/truth.tsx index f08da83..ab465f4 100644 --- a/src/components/new_ui/truth.tsx +++ b/src/components/new_ui/truth.tsx @@ -118,7 +118,7 @@ function Truth() { justifyItems={'center'} initial={{ opacity: 0 }} animate={isMainInView ? { opacity: 1 } : { opacity: 0 }} - transition={{ duration: 0.8, ease: "easeOut" }} + transition={{ duration: 0.5, ease: "easeOut" }} > 想知道更多食用油健康真相? @@ -145,7 +145,7 @@ function Truth() { alignItems={'flex-start'} initial={{ opacity: 0, y: 50 }} animate={isMainInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 50 }} - transition={{ duration: 0.8, delay: 0.4, ease: "easeOut" }} + transition={{ duration: 0.5, delay: 0.2, ease: "easeOut" }} > {truthItems.map((item, index) => ( {renderDescription(item.desc)} @@ -192,7 +192,7 @@ function Truth() { align={'center'} initial={{ opacity: 0, scale: 0.9 }} animate={isTitleInView ? { opacity: 1, scale: 1 } : { opacity: 0, scale: 0.9 }} - transition={{ duration: 0.5, delay: 0.3, ease: "easeOut" }} + transition={{ duration: 0.5, delay: 0.2, ease: "easeOut" }} > 點擊以下銷售點連結 @@ -215,28 +215,28 @@ function Truth() { align={'flex-end'} initial={{ opacity: 0, y: 30 }} animate={isTitleInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 30 }} - transition={{ duration: 0.8, delay: 0.4, ease: "easeOut" }} + transition={{ duration: 0.8, delay: 0.2, ease: "easeOut" }} > {shopImages.map((image, index) => ( @@ -251,7 +251,7 @@ function Truth() { mt={10} initial={{ opacity: 0, scale: 0.9 }} animate={isTitleInView ? { opacity: 1, scale: 1 } : { opacity: 0, scale: 0.9 }} - transition={{ duration: 0.6, delay: 1.6, ease: "easeOut" }} + transition={{ duration: 0.6, delay: 0.6, ease: "easeOut" }} > diff --git a/src/pages/home.tsx b/src/pages/home.tsx index 4c64428..f14b1af 100644 --- a/src/pages/home.tsx +++ b/src/pages/home.tsx @@ -6,10 +6,11 @@ import Qa from '../components/qa' import Oil_info from '../components/oil_info' import Bestoil from '../components/bestoil' import Salespoint from '../components/salespoint' - +import Header2 from '@/components/header2' function HomePage() { return ( <> + diff --git a/src/pages/recipe.tsx b/src/pages/recipe.tsx new file mode 100644 index 0000000..416ed35 --- /dev/null +++ b/src/pages/recipe.tsx @@ -0,0 +1,131 @@ +import { Box, Text, SimpleGrid, Image } from '@chakra-ui/react' +import { InstagramEmbed } from 'react-social-media-embed'; +import Header from '@/components/header'; +import { useEffect, useState } from 'react' + +const igPosts = [ + { + id: 1, + title: "Healthy Oil Recipe 1", + url: "https://www.instagram.com/reel/DQiyajyET7l/?igsh=NzZnbmduNjc0Zjlo" + }, + { + id: 2, + title: "Healthy Oil Recipe 2", + url: "https://www.instagram.com/reel/DO5f01Pj_By/?igsh=NjhhMnpxczllaHQ1" + }, + { + id: 3, + title: "Healthy Oil Recipe 3", + url: "https://www.instagram.com/p/DQicBYxE9IA/?igsh=MWIybmo4YXNxdnBlbw==" + }, + { + id: 4, + title: "Healthy Oil Recipe 4", + url: "https://www.instagram.com/p/DQCAnNrEWfF/?igsh=MXc0Z25qNm9jaWtyNA==" + }, + { + id: 5, + title: "Healthy Oil Recipe 5", + url: "https://www.instagram.com/reel/DQbruJ2Ejpz/?igsh=Mm96NWljMWdyOW56" + }, + { + id: 6, + title: "Healthy Oil Recipe 6", + url: "https://www.instagram.com/reel/DQe5gwTkjCf/?igsh=MXZ2aHRjN3Vnd2RjcQ==" + } +]; + +function Recipe() { + + const [headerHeight, setHeaderHeight] = useState(80); + + useEffect(() => { + const updateHeaderHeight = () => { + const header = document.querySelector('[data-header="true"]'); + if (header) { + const height = header.getBoundingClientRect().height; + setHeaderHeight(height); + } + }; + + const delayedUpdate = () => { + setTimeout(updateHeaderHeight, 100); + }; + + delayedUpdate(); + + const resizeObserver = new ResizeObserver(() => { + setTimeout(updateHeaderHeight, 50); + }); + + const header = document.querySelector('[data-header="true"]'); + if (header) { + resizeObserver.observe(header); + } + + window.addEventListener('resize', delayedUpdate); + + return () => { + window.removeEventListener('resize', delayedUpdate); + resizeObserver.disconnect(); + }; + }, []); + + + return ( + +
+ + + + + {igPosts.map((post) => ( + + + + + {post.title} + + + + ))} + + + + + + ) +} + +export default Recipe; \ No newline at end of file diff --git a/src/router.tsx b/src/router.tsx index 30ecf56..f28b03e 100644 --- a/src/router.tsx +++ b/src/router.tsx @@ -2,6 +2,7 @@ import { createRouter, createRootRoute, createRoute } from '@tanstack/react-rout import Layout from './components/layout' import MainPage from './pages/main' import HomePage from './pages/home' +import RecipePage from './pages/recipe' // Create a root route with layout const rootRoute = createRootRoute({ @@ -22,9 +23,16 @@ const homeRoute = createRoute({ component: HomePage, }) +// Recipe page route +const recipeRoute = createRoute({ + getParentRoute: () => rootRoute, + path: '/recipe', + component: RecipePage, +}) + // Create the router const router = createRouter({ - routeTree: rootRoute.addChildren([indexRoute, homeRoute]), + routeTree: rootRoute.addChildren([indexRoute, homeRoute, recipeRoute]), }) export default router \ No newline at end of file