first commit

This commit is contained in:
2024-10-05 15:04:17 +08:00
parent 792a3d9db1
commit ee746cd61d
44 changed files with 2399 additions and 124 deletions

View File

@@ -0,0 +1,85 @@
"use client"
import React, { useEffect, useState } from 'react'
import Link from 'next/link'
import { FiChevronDown, FiChevronUp } from 'react-icons/fi';
import { CoursesProps } from '@/types'
//define props type
type Props = {
showNav: boolean;
closeNav: () => void
courses: CoursesProps[]
}
const MobileNav = ({ closeNav, showNav, courses }: Props) => {
const [dropdownOpen, setDropdownOpen] = useState(false);
useEffect(() => {
if (showNav) {
document.body.classList.add('overflow-hidden');
} else {
document.body.classList.remove('overflow-hidden');
}
return () => {
document.body.classList.remove('overflow-hidden');
};
}, [showNav]);
const navOpen = showNav ? 'translate-x-0' : 'translate-x-[-100%]'
const navClose = !showNav ? 'translate-x-[-100%]' : 'translate-x-0'
return (
<div>
{/*overlay*/}
<div className={`fixed ${navOpen} ${navClose} transform transition-all duration-500 top-[7vh] inset-x-0 bottom-0 z-[1000]`}>
{/* nav links*/}
<div className={`text-white ${navOpen} fixed flex flex-col h-full w-[80%] sm:w-[60%] bg-[#F9E7E9] z-[10000] `}>
<div className='w-full h-16 flex justify-start items-center border-b-[1.5px] border-[#F5DADF]'>
<Link key={"01"} href={"#"} >
<p className="text-xl ml-6 text-black">
</p>
</Link>
</div>
<div className={`w-full flex flex-col ${dropdownOpen ? "border-b-[0px]" : "border-b-[1.5px]"} border-[#F5DADF]`}>
<div
className='h-16 flex justify-between items-center px-6 cursor-pointer'
onClick={() => setDropdownOpen(!dropdownOpen)}
>
<p className="text-xl text-black"></p>
{dropdownOpen ? <FiChevronUp className='text-black' size={30}/> : <FiChevronDown className='text-black' size={30}/>}
</div>
{dropdownOpen && (
<div>
{courses?.map((course) => (
<div className='bg-[#F5DADF] w-full h-16 flex justify-start items-center border-b-[1.5px] border-[#F9E7E9]'>
<Link key={course.id} href={`/courses/${course.id}`}>
<p className="text-lg text-black ml-8 ">
{course.title}
</p>
</Link>
</div>
))}
</div>
)}
</div>
<div className='w-full h-16 flex justify-start items-center border-b-[1.5px] border-[#F5DADF]'>
<Link key={"03"} href={"#"} >
<p className="text-xl ml-6 text-black">
</p>
</Link>
</div>
</div>
</div>
</div>
)
}
export default MobileNav

134
components/Navbar/Nav.tsx Normal file
View File

@@ -0,0 +1,134 @@
"use client"
import React, { useState, useEffect } from 'react'
import Image from 'next/image'
import Link from 'next/link'
import { FiChevronDown } from "react-icons/fi";
import { HiBars3BottomRight } from 'react-icons/hi2'
import { FaFacebookF, FaYoutube } from "react-icons/fa";
import { RiInstagramFill } from "react-icons/ri";
import { IoMenu, IoClose } from "react-icons/io5";
import { CoursesProps, SettingsProps } from '@/types'
import { colors } from '@/public/themes'
//define props type
type Props = {
openNav: () => void
showNav: boolean
courses: CoursesProps[]
settings: SettingsProps
}
const Nav = ({ openNav, courses, showNav, settings }: Props) => {
const [navBg, setNavBg] = useState(false)
const [dropdownOpen, setDropdownOpen] = useState(false);
useEffect(() => {
const handler = () => {
if (window.scrollY >= 90) {
setNavBg(true)
} else if (window.scrollY <= 90) {
setNavBg(false)
}
}
window.addEventListener("scroll", handler)
return () => {
window.removeEventListener("scroll", handler)
}
}, []);
return (
<div className={`bg-[#F6E5E9] max-sm:bg-[#FFF9F9] h-[7vh] z-[10] w-full transition-all duration-200 `}>
<div className="flex items-center justify-between w-[80%] sm:w-[80%] x1:w-[80%] mx-auto">
<div className='flex items-center space-x-10'>
<Link href={"/"}>
<Image
src="/images/logo.png"
alt='logo'
width={170}
height={170}
className="m1-[-1.5rem] sm:m1-0 mr-4"
/>
</Link>
<div className="flex items-center space-x-15">
<div className='hidden lg:flex items-center space-x-8'>
<Link key={"01"} href={"/"} >
<p className="nav__link">
{"主頁"}
</p>
</Link>
<div key={"02"} className="relative">
<button
className="nav__link flex items-center"
onClick={() => setDropdownOpen(!dropdownOpen)}
>
{"課程"}
<FiChevronDown className='text-gray-400' />
</button>
{dropdownOpen && (
<div className="absolute left-0 top-full mt-1 w-48 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 z-50">
<div className="py-1" role="menu" aria-orientation="vertical" aria-labelledby="options-menu">
{courses.map((course) => (
<a
key={course.id}
href={`/courses/${course.id}`}
className={`block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-mainColor`}
role="menuitem"
>
{course.title}
</a>
))}
</div>
</div>
)}
</div>
<Link key={"03"} href={"#"} >
<p className="nav__link">
{"關於我們"}
</p>
</Link>
</div>
</div>
</div>
{/*button*/}
<div className="flex items-center space-x-5 ">
<div className="flex items-center space-x-2 max-sm:hidden">
<div className="bg-[#DCCECF] rounded-full h-8 w-8 flex items-center justify-center hover:bg-mainColor"
onClick={() => window.open(settings.facebook)} >
<FaFacebookF
className="w-4 h-4 cursor-pointer text-[#F6E5E9]"
/>
</div>
<div className="bg-[#DCCECF] rounded-full h-8 w-8 flex items-center justify-center hover:bg-mainColor"
onClick={() => window.open(settings.instagram)} >
<RiInstagramFill
className="w-4 h-4 cursor-pointer text-[#F6E5E9]"
/>
</div>
<div className="bg-[#DCCECF] rounded-full h-8 w-8 flex items-center justify-center hover:bg-mainColor"
onClick={() => window.open(settings.youtube)} >
<FaYoutube
className="w-4 h-4 cursor-pointer text-[#F6E5E9]"
/>
</div>
</div>
{/*burger*/}
{showNav ? (
<IoClose
onClick={openNav}
className="w-8 h-8 cursor-pointer text-mainColor lg:hidden ml-2"
/>
) : (
<IoMenu
id='menubutton'
onClick={openNav}
className="w-8 h-8 cursor-pointer text-mainColor lg:hidden ml-2"
/>
)}
</div>
</div>
</div>
)
}
export default Nav

View File

@@ -0,0 +1,20 @@
"use client"
import React, {useState} from 'react'
import MobileNav from './MobileNav'
import Nav from './Nav'
import { CoursesProps,SettingsProps } from '@/types'
const ResponsiveNav = ({ courses, settings }: { courses: CoursesProps[], settings: SettingsProps }) => {
const [showNav, setShowNav] = useState(false)
const toggleNavHandler = () => setShowNav(!showNav)
const showNavHandler = () => setShowNav(true)
const closeNavHandler = () => setShowNav(false)
return (
<div>
<Nav openNav={toggleNavHandler} showNav={showNav} courses={courses} settings={settings} />
<MobileNav showNav={showNav} closeNav={closeNavHandler} courses={courses} />
</div>
)
}
export default ResponsiveNav