diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..09a64a9
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,25 @@
+
+FROM node:18-alpine
+
+RUN mkdir -p /app
+
+WORKDIR /app
+
+COPY package.json ./
+
+RUN npm install
+
+RUN npm install --save-dev
+
+
+COPY . /app
+
+# Build the Next.js app
+RUN npm run build
+
+# Expose the port the app will run on
+EXPOSE 3000
+
+COPY . .
+
+CMD ["npm", "run", "dev"]
\ No newline at end of file
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..2c58a68
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,20 @@
+services:
+ app:
+ build:
+ context: .
+ dockerfile: Dockerfile
+ container_name: healthy-oil
+
+ env_file:
+ - .env
+ ports:
+ - "3005:3000"
+ volumes:
+ - .:/app
+ - /app/node_modules
+
+
+
+ networks:
+ - gitea_network
+
diff --git a/index.html b/index.html
index e4b78ea..a44f028 100644
--- a/index.html
+++ b/index.html
@@ -2,9 +2,9 @@
-
+
- Vite + React + TS
+ Healthy Oil
diff --git a/package-lock.json b/package-lock.json
index 59e1677..0423c8c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -19,7 +19,9 @@
"next-themes": "^0.4.6",
"react": "^19.0.0",
"react-dom": "^19.0.0",
+ "react-facebook": "^9.0.12",
"react-icons": "^5.5.0",
+ "react-social-plugins": "^2.1.0",
"snippet": "^0.1.0"
},
"devDependencies": {
@@ -4897,6 +4899,18 @@
"integrity": "sha512-nMoGWW2HurtuJf6XAL56FWTDCWLOTSsanrgwOyaR5Y4e3zfG5N/0cU5xWZSEU3tBxhQugRbV1xL9jb+ug7yZww==",
"license": "MIT"
},
+ "node_modules/loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "license": "MIT",
+ "dependencies": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ },
+ "bin": {
+ "loose-envify": "cli.js"
+ }
+ },
"node_modules/lru-cache": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
@@ -5472,6 +5486,17 @@
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
+ "node_modules/prop-types": {
+ "version": "15.8.1",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+ "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.4.0",
+ "object-assign": "^4.1.1",
+ "react-is": "^16.13.1"
+ }
+ },
"node_modules/proxy-compare": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/proxy-compare/-/proxy-compare-3.0.1.tgz",
@@ -5538,6 +5563,21 @@
"react": "^19.0.0"
}
},
+ "node_modules/react-facebook": {
+ "version": "9.0.12",
+ "resolved": "https://registry.npmjs.org/react-facebook/-/react-facebook-9.0.12.tgz",
+ "integrity": "sha512-u7L9wWEG8/UR1kj3JRvHR5SR/cBvZkC4ZCnIt4ZmXMpg4LGVJkihcYIb2/L3FOHUsNt6p9k6jpA+7Cz3zD34iA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.20.6"
+ },
+ "engines": {
+ "node": ">= 6.0.0"
+ },
+ "peerDependencies": {
+ "react": ">= 16"
+ }
+ },
"node_modules/react-icons": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz",
@@ -5563,6 +5603,30 @@
"node": ">=0.10.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",
+ "integrity": "sha512-TiCJI8DGtMn+NjkjgH0QoGrAl3Mplg//c0/r8nF13nl8fgBzEP0QTvBR3pJnc+Klb4N5oBEeWim6jWntjW/eSg==",
+ "license": "MIT",
+ "dependencies": {
+ "prop-types": "^15.7.2",
+ "react": "^16.13.1"
+ }
+ },
+ "node_modules/react-social-plugins/node_modules/react": {
+ "version": "16.14.0",
+ "resolved": "https://registry.npmjs.org/react/-/react-16.14.0.tgz",
+ "integrity": "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==",
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.1.0",
+ "object-assign": "^4.1.1",
+ "prop-types": "^15.6.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/readdirp": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
diff --git a/package.json b/package.json
index b080d04..ba986be 100644
--- a/package.json
+++ b/package.json
@@ -21,7 +21,9 @@
"next-themes": "^0.4.6",
"react": "^19.0.0",
"react-dom": "^19.0.0",
+ "react-facebook": "^9.0.12",
"react-icons": "^5.5.0",
+ "react-social-plugins": "^2.1.0",
"snippet": "^0.1.0"
},
"devDependencies": {
diff --git a/public/images/background.jpg b/public/images/background.jpg
new file mode 100644
index 0000000..3914463
Binary files /dev/null and b/public/images/background.jpg differ
diff --git a/images/background.png b/public/images/background.png
similarity index 100%
rename from images/background.png
rename to public/images/background.png
diff --git a/images/best5.png b/public/images/best5.png
similarity index 100%
rename from images/best5.png
rename to public/images/best5.png
diff --git a/images/bgyellow.jpg b/public/images/bgyellow.jpg
similarity index 100%
rename from images/bgyellow.jpg
rename to public/images/bgyellow.jpg
diff --git a/images/bigheart.png b/public/images/bigheart.png
similarity index 100%
rename from images/bigheart.png
rename to public/images/bigheart.png
diff --git a/images/conpareheart.png b/public/images/conpareheart.png
similarity index 100%
rename from images/conpareheart.png
rename to public/images/conpareheart.png
diff --git a/images/cook_mb.png b/public/images/cook_mb.png
similarity index 100%
rename from images/cook_mb.png
rename to public/images/cook_mb.png
diff --git a/images/cook_pc.png b/public/images/cook_pc.png
similarity index 100%
rename from images/cook_pc.png
rename to public/images/cook_pc.png
diff --git a/images/headerlogo.png b/public/images/headerlogo.png
similarity index 100%
rename from images/headerlogo.png
rename to public/images/headerlogo.png
diff --git a/images/hero1oil.png b/public/images/hero1oil.png
similarity index 100%
rename from images/hero1oil.png
rename to public/images/hero1oil.png
diff --git a/images/hero1text.png b/public/images/hero1text.png
similarity index 100%
rename from images/hero1text.png
rename to public/images/hero1text.png
diff --git a/public/images/hero2title.png b/public/images/hero2title.png
new file mode 100644
index 0000000..1e28f60
Binary files /dev/null and b/public/images/hero2title.png differ
diff --git a/public/images/hk.png b/public/images/hk.png
new file mode 100644
index 0000000..c0afc8e
Binary files /dev/null and b/public/images/hk.png differ
diff --git a/images/mboilinfogroup.png b/public/images/mboilinfogroup.png
similarity index 100%
rename from images/mboilinfogroup.png
rename to public/images/mboilinfogroup.png
diff --git a/images/mboilinfotitle.png b/public/images/mboilinfotitle.png
similarity index 100%
rename from images/mboilinfotitle.png
rename to public/images/mboilinfotitle.png
diff --git a/images/oil.png b/public/images/oil.png
similarity index 100%
rename from images/oil.png
rename to public/images/oil.png
diff --git a/images/oilchart.png b/public/images/oilchart.png
similarity index 100%
rename from images/oilchart.png
rename to public/images/oilchart.png
diff --git a/images/oilinfobg.png b/public/images/oilinfobg.png
similarity index 100%
rename from images/oilinfobg.png
rename to public/images/oilinfobg.png
diff --git a/images/oilinfofooterbg.png b/public/images/oilinfofooterbg.png
similarity index 100%
rename from images/oilinfofooterbg.png
rename to public/images/oilinfofooterbg.png
diff --git a/images/oilinfoheadertitle.png b/public/images/oilinfoheadertitle.png
similarity index 100%
rename from images/oilinfoheadertitle.png
rename to public/images/oilinfoheadertitle.png
diff --git a/images/oilinfooil.png b/public/images/oilinfooil.png
similarity index 100%
rename from images/oilinfooil.png
rename to public/images/oilinfooil.png
diff --git a/images/oilinfotitle.png b/public/images/oilinfotitle.png
similarity index 100%
rename from images/oilinfotitle.png
rename to public/images/oilinfotitle.png
diff --git a/images/oilmobile.png b/public/images/oilmobile.png
similarity index 100%
rename from images/oilmobile.png
rename to public/images/oilmobile.png
diff --git a/images/oldman.jpg b/public/images/oldman.jpg
similarity index 100%
rename from images/oldman.jpg
rename to public/images/oldman.jpg
diff --git a/images/pcoilinfogroup.png b/public/images/pcoilinfogroup.png
similarity index 100%
rename from images/pcoilinfogroup.png
rename to public/images/pcoilinfogroup.png
diff --git a/images/people2.png b/public/images/people2.png
similarity index 100%
rename from images/people2.png
rename to public/images/people2.png
diff --git a/public/images/pp.png b/public/images/pp.png
new file mode 100644
index 0000000..fb2ab2c
Binary files /dev/null and b/public/images/pp.png differ
diff --git a/images/q1.png b/public/images/q1.png
similarity index 100%
rename from images/q1.png
rename to public/images/q1.png
diff --git a/images/q2.png b/public/images/q2.png
similarity index 100%
rename from images/q2.png
rename to public/images/q2.png
diff --git a/images/q3.png b/public/images/q3.png
similarity index 100%
rename from images/q3.png
rename to public/images/q3.png
diff --git a/images/q4.png b/public/images/q4.png
similarity index 100%
rename from images/q4.png
rename to public/images/q4.png
diff --git a/images/q5.png b/public/images/q5.png
similarity index 100%
rename from images/q5.png
rename to public/images/q5.png
diff --git a/images/qtext.png b/public/images/qtext.png
similarity index 100%
rename from images/qtext.png
rename to public/images/qtext.png
diff --git a/images/text1.png b/public/images/text1.png
similarity index 100%
rename from images/text1.png
rename to public/images/text1.png
diff --git a/images/title1.png b/public/images/title1.png
similarity index 100%
rename from images/title1.png
rename to public/images/title1.png
diff --git a/public/images/we.png b/public/images/we.png
new file mode 100644
index 0000000..044baff
Binary files /dev/null and b/public/images/we.png differ
diff --git a/images/woodtable.png b/public/images/woodtable.png
similarity index 100%
rename from images/woodtable.png
rename to public/images/woodtable.png
diff --git a/public/logo_.svg b/public/logo_.svg
new file mode 100644
index 0000000..1f0465d
--- /dev/null
+++ b/public/logo_.svg
@@ -0,0 +1,9 @@
+
\ No newline at end of file
diff --git a/src/App.tsx b/src/App.tsx
index 6c7b523..6df43c3 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,7 +1,6 @@
import {
Box,
Container,
- Text,
} from '@chakra-ui/react'
import Header from './components/header'
@@ -11,7 +10,8 @@ import Compare from './components/compare'
import Qa from './components/qa'
import Oil_info from './components/oil_info'
import Bestoil from './components/bestoil'
-
+import Salespoint from './components/salespoint'
+import Footer from './components/footer'
function App() {
return (
<>
@@ -34,17 +34,15 @@ function App() {
+
+
+
{/* Info Section */}
{/* Footer */}
-
-
- 服務專線:29437810
-
-
-
+
>
)
diff --git a/src/components/bestoil.tsx b/src/components/bestoil.tsx
index cd0778d..25bf719 100644
--- a/src/components/bestoil.tsx
+++ b/src/components/bestoil.tsx
@@ -1,13 +1,32 @@
import { Box, Stack, Image, Flex, useBreakpointValue, Text } from '@chakra-ui/react'
import { colors } from '../colors';
+import { motion, useInView } from 'framer-motion'
+import { useRef } from 'react'
+
+// Create motion components from Chakra components
+const MotionBox = motion(Box);
+const MotionStack = motion(Stack);
+
function Bestoil() {
const cook = useBreakpointValue({
base: "/images/cook_mb.png",
sm: "/images/cook_mb.png",
md: "/images/cook_pc.png",
-
});
+
+ // Create refs for elements we want to animate
+ const bestOilRef = useRef(null);
+ const oilChartRef = useRef(null);
+ const cookRef = useRef(null);
+ const oilCubesRef = useRef(null);
+
+ // Check if elements are in view
+ const isBestOilInView = useInView(bestOilRef, { once: true });
+ const isOilChartInView = useInView(oilChartRef, { once: true });
+ const isCookInView = useInView(cookRef, { once: true });
+ const isOilCubesInView = useInView(oilCubesRef, { once: true });
+
const oilCube = [
{
bgColor: 'linear-gradient(to right,#00609E ,#008FD0,#00609E )',
@@ -35,53 +54,63 @@ function Bestoil() {
text: '低飽和脂肪,穩定性高,適合高溫烹調'
},
]
- const formatText = (text: string) => {
- return text.split('\n').map((line, i) => (
-
- {line.split('\t').map((segment, j) => (
- j === 0 ? segment : {segment}
- ))}
- {i < text.split('\n').length - 1 &&
}
-
- ));
- };
return (
-
-
-
+
+
+
+
+
+
-
+
+
+
-
-
+
{oilCube.map((item, index) => (
-
{item.text}
-
+
))}
-
-
+
+ {"選擇「營萃護心油」,助你和家人攝取理想脂肪酸比例,食得安心,護心更放心!"}
+
-
-
-
)
-
-
}
export default Bestoil
diff --git a/src/components/compare.tsx b/src/components/compare.tsx
index 10bdc38..42fc791 100644
--- a/src/components/compare.tsx
+++ b/src/components/compare.tsx
@@ -1,7 +1,6 @@
-import { Box, Stack, Image, Text, Flex, SimpleGrid } from '@chakra-ui/react'
-import { } from '../colors';
+import { Box, Stack, Image, Flex, SimpleGrid } from '@chakra-ui/react'
import {useRef } from 'react';
-import { motion, useInView } from 'framer-motion';
+import { motion } from 'framer-motion';
// Create motion versions of Chakra components
diff --git a/src/components/footer.tsx b/src/components/footer.tsx
new file mode 100644
index 0000000..6f0675b
--- /dev/null
+++ b/src/components/footer.tsx
@@ -0,0 +1,43 @@
+import { Stack, Flex, Image, Text, } from '@chakra-ui/react';
+import { colors } from '../colors';
+
+function Footer() {
+ const currentYear = new Date().getFullYear();
+ return (
+
+
+ {"查詢:29437810"}
+
+
+
+
+ {"【積極求變 健康向前】"}
+
+
+
+
+ {`Copyright © ${currentYear}合興食油(香港)有限公司 版權所有,不得轉載。`}
+
+
+
+ );
+}
+
+export default Footer;
\ No newline at end of file
diff --git a/src/components/hero1.tsx b/src/components/hero1.tsx
index dd1bbd7..5cccd6f 100644
--- a/src/components/hero1.tsx
+++ b/src/components/hero1.tsx
@@ -48,7 +48,7 @@ function Hero1() {
overflow="hidden"
position="relative"
w="100%"
- bgImage={"url('/images/background.png')"}
+ bgImage={"url('/images/background.jpg')"}
bgSize="cover"
backgroundPosition="center"
bgRepeat="no-repeat"
diff --git a/src/components/hero2.tsx b/src/components/hero2.tsx
index f961bfd..002a6f7 100644
--- a/src/components/hero2.tsx
+++ b/src/components/hero2.tsx
@@ -1,6 +1,6 @@
import { Box, Stack, Image, Text, Flex, SimpleGrid } from '@chakra-ui/react'
import { colors } from '../colors';
-import { useEffect, useRef, useState } from 'react';
+import { useEffect, useRef } from 'react';
import { motion, useInView, useAnimation } from 'framer-motion'
// Create motion components from Chakra UI components
@@ -12,7 +12,6 @@ const MotionText = motion(Text);
function Hero2() {
const textStackRef = useRef(null);
const imageStackRef = useRef(null);
- const [textStackHeight, setTextStackHeight] = useState(null);
// Create refs and animation controls for scroll-based animations
const containerRef = useRef(null);
@@ -35,8 +34,7 @@ function Hero2() {
useEffect(() => {
const updateHeight = () => {
if (textStackRef.current) {
- const height = textStackRef.current.offsetHeight;
- setTextStackHeight(height);
+ // const height = textStackRef.current.offsetHeight;
}
};
@@ -71,7 +69,7 @@ function Hero2() {
align={"center"}
>
@@ -192,5 +190,4 @@ function Hero2() {
);
}
-
export default Hero2;
diff --git a/src/components/oil_info.tsx b/src/components/oil_info.tsx
index 49b65f7..ecaef9e 100644
--- a/src/components/oil_info.tsx
+++ b/src/components/oil_info.tsx
@@ -1,7 +1,7 @@
import { Box, Stack, Image, Flex, useBreakpointValue, Text } from '@chakra-ui/react'
import { motion, useInView, useAnimation } from 'framer-motion'
import { useRef, useEffect } from 'react'
-const MotionFlex = motion(Flex);
+
function Oil_info() {
const oilinfotitle = useBreakpointValue({
base: "/images/mboilinfotitle.png",
@@ -15,6 +15,7 @@ function Oil_info() {
md: "/images/pcoilinfogroup.png",
});
+
// Animation controls for the header section
const headerControls = useAnimation();
const headerRef = useRef(null);
@@ -70,11 +71,8 @@ function Oil_info() {
bgColor={'#4E8C34'}
>
-
-
+
{/* Rest of the component remains the same until the footer image */}
@@ -222,6 +220,12 @@ function Oil_info() {
-
-
+
+
);
}
export default Oil_info;
diff --git a/src/components/salespoint.tsx b/src/components/salespoint.tsx
new file mode 100644
index 0000000..7719763
--- /dev/null
+++ b/src/components/salespoint.tsx
@@ -0,0 +1,146 @@
+import { Box, Stack, Image, Text, Flex, Link } from '@chakra-ui/react'
+import { colors } from '../colors';
+import { useEffect, useRef } from 'react';
+import { motion, useInView } from 'framer-motion'
+
+function Salespoint() {
+ const shopImages = [
+ {
+ image: '/images/pp.png',
+ link: 'https://www.pns.hk/zh-hk/all-brands/b/112546/%E7%8D%85%E7%90%83%E5%98%9C',
+ },
+ {
+ image: '/images/we.png',
+ link: 'https://www.wellcome.com.hk/zh-hant/search?keyword=%E7%8D%85%E7%90%83%E5%98%9C&page=1',
+ },
+ {
+ image: '/images/hk.png',
+ link: 'https://www.hktvmall.com/hktv/zh/search_a?keyword=%E7%8D%85%E7%90%83%E5%98%9C',
+ },
+ ]
+
+ const fbContainerRef = useRef(null);
+ const titleRef = useRef(null);
+ const isTitleInView = useInView(titleRef, { once: true });
+
+
+ // Load Facebook SDK and initialize the plugin
+ useEffect(() => {
+ // Add Facebook SDK if it doesn't exist
+ if (!document.getElementById('facebook-jssdk')) {
+ const script = document.createElement('script');
+ script.id = 'facebook-jssdk';
+ script.src = 'https://connect.facebook.net/en_US/sdk.js#xfbml=1&version=v18.0';
+ script.async = true;
+ script.defer = true;
+ document.body.appendChild(script);
+ }
+
+ // Parse XFBML when SDK is loaded
+ const handleSDKLoad = () => {
+ if ((window as any).FB && fbContainerRef.current) {
+ (window as any).FB.XFBML.parse(fbContainerRef.current);
+ }
+ };
+
+ // Check if FB is already loaded
+ if ((window as any).FB) {
+ handleSDKLoad();
+ } else {
+ // Listen for SDK load
+ (window as any).fbAsyncInit = handleSDKLoad;
+ }
+
+ return () => {
+ // Clean up
+ (window as any).fbAsyncInit = undefined;
+ };
+ }, []);
+
+ return (
+
+
+
+
+ 銷售點
+
+
+
+
+
+ {shopImages.map((image, index) => (
+
+
+
+
+
+
+
+ ))}
+
+
+ {/* Facebook Page Plugin */}
+
+
+
+
+
+
+
+ )
+}
+
+export default Salespoint;
diff --git a/src/types/global.d.ts b/src/types/global.d.ts
new file mode 100644
index 0000000..53b153f
--- /dev/null
+++ b/src/types/global.d.ts
@@ -0,0 +1,7 @@
+interface Window {
+ FB?: {
+ XFBML: {
+ parse: (element?: Element) => void;
+ };
+ };
+ }
\ No newline at end of file