Skip to content

Commit

Permalink
Merge pull request NCUAppTeam#115 from 1989ONCE/main
Browse files Browse the repository at this point in the history
專案架構
  • Loading branch information
1989ONCE authored Oct 3, 2024
2 parents da4ff0f + 3f472de commit 11c6067
Show file tree
Hide file tree
Showing 38 changed files with 1,755 additions and 206 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ dev-dist
# Editor directories and files
.idea
.DS_Store
.env
*.suo
*.ntvs*
*.njsproj
Expand Down
629 changes: 488 additions & 141 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"@supabase/supabase-js": "^2.45.3",
"@tanstack/react-router": "^1.56.2",
"react": "^18.3.1",
"react-dom": "^18.3.1"
"react-dom": "^18.3.1",
"supabase": "^1.200.3"
},
"devDependencies": {
"@playwright/test": "^1.47.0",
Expand All @@ -27,6 +28,7 @@
"@vite-pwa/assets-generator": "^0.2.4",
"@vitejs/plugin-react": "^4.2.1",
"autoprefixer": "^10.4.20",
"daisyui": "^4.12.10",
"eslint": "^8.57.0",
"eslint-plugin-react-hooks": "^4.6.2",
"eslint-plugin-react-refresh": "^0.4.6",
Expand Down
14 changes: 0 additions & 14 deletions src/components/Button.tsx

This file was deleted.

9 changes: 9 additions & 0 deletions src/components/Common/Center.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import ChildrenProps from '../interface/ChildrenProps';

export const Center = ({ children }: ChildrenProps) => {
return (
<div className="flex mx-auto">
{children}
</div>
);
};
9 changes: 9 additions & 0 deletions src/components/Common/HStack.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import ChildrenProps from '../interface/ChildrenProps';

export const HStack = ({ children, className }: ChildrenProps) => {
return (
<div className={`flex flex-row ${className}`}>
{children}
</div>
);
};
10 changes: 10 additions & 0 deletions src/components/Common/Image.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import ImageProps from '../interface/ImageProps';

export const Image = ({ children, className, src, alt }: ImageProps) => {
return (
<>
<img className={className} src={src} alt={alt} />
{children}
</>
);
};
9 changes: 9 additions & 0 deletions src/components/Common/VStack.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import ChildrenProps from '../interface/ChildrenProps';

export const VStack = ({ children, className }: ChildrenProps) => {
return (
<div className={`flex flex-col ${className}`}>
{children}
</div>
);
};
9 changes: 9 additions & 0 deletions src/components/Common/customButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import ButtonProps from "../interface/ButtonProps";

export const Button = ({ children, type, className, onClick }: ButtonProps) => (
<button onClick={onClick} type={type} className={className}>

{children}

</button>
);
48 changes: 48 additions & 0 deletions src/components/DrawerOption.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { Link } from "@tanstack/react-router";
import { useState } from "react";
import { HStack, SidebarArrowDownIcon, SidebarArrowRightIcon, VStack } from "../components";

const options = [
{ name: "首頁", engName: "Home", pageNav: "/" },
{ name: "活動/揪人", engName: "Events", pageNav: "/events" },
{ name: "拍賣", engName: "Market", pageNav: "/sales" },
{ name: "行事曆", engName: "Calendar", pageNav: "/calendar" },
{ name: "地圖", engName: "Map", pageNav: "/map" },
{ name: "今晚吃什麼", engName: "Dinner Decider", pageNav: "/dinner" },
];

export const DrawerOption = () => {
const [openOptions, setOpenOptions] = useState<{ [key: string]: boolean }>({});

const toggleOption = (name: string) => {
setOpenOptions((prev) => {
return {
...prev,
[name]: !prev[name],
};
});
};

return (
<VStack id="all-nav-func">
{options.map((option) => (
<HStack className="bg-blue-200" key={option.name}>
<div className="flex items-center" onClick={() => toggleOption(option.name)}>
{openOptions[option.name] ? (
<SidebarArrowDownIcon fill="currentColor" stroke={"#B1B1B1"} size={20} />
) : (
<SidebarArrowRightIcon fill="currentColor" stroke={"#B1B1B1"} size={20} />
)}
</div>
<Link to={option.pageNav}>
<li className="bg-white">
<VStack className="justify-start">
<p className="bg-green-100">{option.name}({option.engName})</p>
</VStack>
</li>
</Link>
</HStack>
))}
</VStack>
);
};
53 changes: 53 additions & 0 deletions src/components/DrawerSideBar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { Image, VStack } from "../components";
import { supabase } from "../utils/supabase";
import { DrawerOption } from "./DrawerOption";


const signOut = async () => {
await supabase.auth.signOut().then(() => {
window.location.href = '/';
});
};

export const DrawerSideBar = ({ name, avatar }: { name: string, avatar: string }) => {
return (
<div className="flex w-fit drawer">
<input id="my-drawer" type="checkbox" className="drawer-toggle" />


<div className="drawer-content">
<label htmlFor="my-drawer" className="drawer-button">
<Image src={avatar} children={undefined} className='w-10 rounded-full'></Image>
</label>
</div>

{/* Indise Drawer */}
<div className="drawer-side grid content-between">
<label htmlFor="my-drawer" aria-label="close sidebar" className="drawer-overlay"></label>

<ul className="menu bg-base-200 text-base-content h-screen w-80 p-4 grid">
{/* Sidebar content here */}
<VStack className="h-full self-start">
<Image src={avatar} children={undefined} className='mb-2 w-10 rounded-full'></Image>
<p className="font-bold">{name}</p>
<p className="text-xs">View Profile</p>


<div className="divider divider-neutral" />

<DrawerOption />


</VStack>

<div className="self-end mb-5">
<div className="divider divider-neutral" />
<p className="text-left text-lg">Settings</p>
<p className="text-left text-lg">About Us</p>
<p className="text-left text-lg" onClick={signOut}>Sign Out</p>
</div>
</ul>
</div>
</div>
);
};
13 changes: 0 additions & 13 deletions src/components/HStack.tsx

This file was deleted.

61 changes: 61 additions & 0 deletions src/components/Header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { HStack } from "../components";
import { supabase } from "../utils/supabase";
import { DrawerSideBar } from "./DrawerSideBar";



import React, { useEffect, useState } from 'react';

export const Header: React.FC = () => {

const [userName, setUserName] = useState<string>('');
const [userAvatar, setUserAvatar] = useState<string>('');
const [error, setError] = useState<unknown>('');

useEffect(() => {
const fetchData = async () => {
try {
const userId = (await supabase.auth.getUser()).data?.user?.id;
if (!userId) {
throw new Error('User ID is undefined');
}
const { data } = await supabase
.from('members')
.select(`*, identities ( identity_no, identity_name )`)
.eq('uuid', userId);

if (data && data.length > 0) {
setUserName(data[0].name);
setUserAvatar(data[0].avatar);
} else {
throw new Error('User data not found');
}
} catch (error: unknown) {
if (error instanceof Error) {
setError(error.message);
} else {
setError(String(error));
}
}
};
fetchData();
}, []);

if (!userName || !userAvatar) {
return <div>Loading...</div>;
}
if (error) {
console.log('error', error);
}

return (
<div className="p-2 gap-2 justify-start">
<HStack className='items-center'>
<DrawerSideBar name={userName} avatar={userAvatar} />
<div className='flex flex-1 justify-center'>
<span className='mr-10'>NCU App</span>
</div>
</HStack>
</div>
);
};
21 changes: 21 additions & 0 deletions src/components/icons/BasicIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react';
import IconProps from '../interface/IconProps';

export const BasicIcon: React.FC<IconProps & { children: React.ReactNode }> = ({ fill = 'currentColor', stroke = 'currentColor', size = 24, children }) => (
<svg
xmlns="http://www.w3.org/2000/svg"
fill={fill}
viewBox="0 0 24 24"
strokeWidth={1.5}
stroke={stroke}
width={size}
height={size}
>
{children}

</svg>



);

16 changes: 16 additions & 0 deletions src/components/icons/CalendarIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@

import React from 'react';
import IconProps from '../interface/IconProps';
import { BasicIcon } from './BasicIcon';

export const CalendarIcon: React.FC<IconProps> = ({ fill, stroke, size }) => (
<BasicIcon fill={fill} stroke={stroke} size={size}>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 0 1 2.25-2.25h13.5A2.25 2.25 0 0 1 21 7.5v11.25m-18 0A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75m-18 0v-7.5A2.25 2.25 0 0 1 5.25 9h13.5A2.25 2.25 0 0 1 21 11.25v7.5"
/>
</BasicIcon>
);

export default CalendarIcon;
16 changes: 16 additions & 0 deletions src/components/icons/LogoutIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@

import React from 'react';
import IconProps from '../interface/IconProps';
import { BasicIcon } from './BasicIcon';

export const LogoutIcon: React.FC<IconProps> = ({ fill, stroke, size }) => (
<BasicIcon fill={fill} stroke={stroke} size={size}>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M15.75 9V5.25A2.25 2.25 0 0 0 13.5 3h-6a2.25 2.25 0 0 0-2.25 2.25v13.5A2.25 2.25 0 0 0 7.5 21h6a2.25 2.25 0 0 0 2.25-2.25V15m3 0 3-3m0 0-3-3m3 3H9"
/>
</BasicIcon>
);

export default LogoutIcon;
12 changes: 12 additions & 0 deletions src/components/icons/SidebarArrowDownIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

import React from 'react';
import IconProps from '../interface/IconProps';
import { BasicIcon } from './BasicIcon';

export const SidebarArrowDownIcon: React.FC<IconProps> = ({ fill, stroke, size }) => (
<BasicIcon fill={fill} stroke={stroke} size={size}>
<path fillRule="evenodd" d="M18.425 10.271C19.499 8.967 18.57 7 16.88 7H7.12c-1.69 0-2.618 1.967-1.544 3.271l4.881 5.927a2 2 0 0 0 3.088 0l4.88-5.927Z" clipRule="evenodd" />
</BasicIcon>
);

export default SidebarArrowDownIcon;
12 changes: 12 additions & 0 deletions src/components/icons/SidebarArrowRightIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

import React from 'react';
import IconProps from '../interface/IconProps';
import { BasicIcon } from './BasicIcon';

export const SidebarArrowRightIcon: React.FC<IconProps> = ({ fill, stroke, size }) => (
<BasicIcon fill={fill} stroke={stroke} size={size}>
<path fillRule="evenodd" d="M10.271 5.575C8.967 4.501 7 5.43 7 7.12v9.762c0 1.69 1.967 2.618 3.271 1.544l5.927-4.881a2 2 0 0 0 0-3.088l-5.927-4.88Z" clipRule="evenodd" />
</BasicIcon>
);

export default SidebarArrowRightIcon;
13 changes: 13 additions & 0 deletions src/components/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Common Components
export { Center } from './Common/Center';
export { Button } from './Common/customButton';
export { HStack } from './Common/HStack';
export { Image } from './Common/Image';
export { VStack } from './Common/VStack';
export { Header } from './Header';
// Icons
export { CalendarIcon } from './icons/CalendarIcon';
export { LogoutIcon } from './icons/LogoutIcon';
export { SidebarArrowDownIcon } from './icons/SidebarArrowDownIcon';
export { SidebarArrowRightIcon } from './icons/SidebarArrowRightIcon';

9 changes: 9 additions & 0 deletions src/components/interface/ButtonProps.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React from 'react';

interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
children: React.ReactNode;
type?: 'submit' | 'reset' | 'button';
className?: string;
}

export default ButtonProps;
7 changes: 7 additions & 0 deletions src/components/interface/ChildrenProps.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { ReactNode } from 'react';

interface ChildrenProps extends React.HTMLAttributes<HTMLDivElement> {
children: ReactNode;
className?: string;

}export default ChildrenProps;
7 changes: 7 additions & 0 deletions src/components/interface/IconProps.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
interface IconProps {
fill?: string | 'currentColor' | 'none';
stroke?: string;
size?: number;
}

export default IconProps;
Loading

0 comments on commit 11c6067

Please sign in to comment.