Skip to content

Commit

Permalink
Merge pull request #66 from bakaqc/feature/user-interface
Browse files Browse the repository at this point in the history
Implement User Interface
  • Loading branch information
theqi106 authored Dec 29, 2024
2 parents 55a92c4 + 1f33ebd commit 0daaccb
Show file tree
Hide file tree
Showing 46 changed files with 1,815 additions and 14 deletions.
22 changes: 14 additions & 8 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,34 @@
"preview": "vite preview"
},
"dependencies": {
"@material-tailwind/react": "2.1.10",
"axios": "1.7.9",
"react": "18.3.1",
"react-dom": "18.3.1"
"react-dom": "18.3.1",
"react-icon": "1.0.0",
"react-icons": "^5.4.0",
"react-redux": "^9.2.0",
"react-router-dom": "^7.1.0",
"slick-carousel": "^1.8.1"
},
"devDependencies": {
"@eslint/js": "9.17.0",
"@types/react": "18.3.17",
"@types/react-dom": "18.3.5",
"@vitejs/plugin-react-swc": "3.5.0",
"autoprefixer": "^10.4.20",
"eslint": "9.17.0",
"eslint-plugin-react-hooks": "5.0.0",
"eslint-plugin-react-refresh": "0.4.16",
"globals": "15.13.0",
"postcss": "8.4.49",
"redux": "5.0.1",
"redux-persist": "6.0.0",
"redux-thunk": "3.1.0",
"tailwindcss": "3.4.17",
"typescript": "5.6.2",
"typescript-eslint": "8.18.1",
"vite": "6.0.3",
"vite-tsconfig-paths": "5.1.4",
"postcss": "8.4.49",
"redux": "5.0.1",
"redux-persist": "6.0.0",
"redux-thunk": "3.1.0",
"tailwindcss": "3.4.17",
"autoprefixer": "^10.4.20"
"vite-tsconfig-paths": "5.1.4"
}
}
387 changes: 387 additions & 0 deletions frontend/pnpm-lock.yaml

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions frontend/postcss.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
43 changes: 43 additions & 0 deletions frontend/public/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>Evora</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
21 changes: 19 additions & 2 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,26 @@
import React from 'react';
import { Route, Routes } from 'react-router-dom';

import {
Home,
HomePage,
LoginAdmin,
LoginUser,
RegisterUser,
} from '@/containers/public';
import { path } from '@/ultils/constant';

const App: React.FC = () => {
return (
<div>
<h1 style={{ textAlign: 'center' }}>Welcome to Evora!</h1>
<div className="overflow-hidden">
<Routes>
<Route path={path.HOME} element={<Home />}>
<Route path="*" element={<HomePage />} />
</Route>
<Route path={path.LOGIN_USER} element={<LoginUser />} />
<Route path={path.LOGIN_ADMIN} element={<LoginAdmin />} />
<Route path={path.REGISTER_USER} element={<RegisterUser />} />
</Routes>
</div>
);
};
Expand Down
Empty file removed frontend/src/assets/.gitkeep
Empty file.
Binary file added frontend/src/assets/bg.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/src/assets/hero.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/src/assets/logo.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/src/assets/logo1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions frontend/src/assets/review-UI.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
MVP: https://evora-17c.onrender.com
Feedback UI: Nên follow vào MVP để điều chỉnh
- Web dùng full tiếng Việt
- Login cho User:
+ Form nhỏ lại tí hoặc thêm content j đó vào phần bên phải chứ trống quá
+ Chữ trong button Login hơi nhỏ
- Login cho Admin: thêm phần Quên mật khẩu
- Homepage:
+ Tích hợp phần header phía trên vào thanh nav bar cho gọn
+ Category trên nav bar chuyển xuống dưới thay bằng các option khác follow MVP như: Sự kiện, Đơn vị tổ chức, Giới thiệu,...
+ Copy banner MVP thêm vào ngay bên dưới nav bar
Empty file removed frontend/src/components/.gitkeep
Empty file.
44 changes: 44 additions & 0 deletions frontend/src/components/Banner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React from 'react';
// Đảm bảo đường dẫn hình ảnh đúng
import { NavLink } from 'react-router-dom';

import hero from '@/assets/hero.jpg';
import { path } from '@/ultils/constant';

const Banner: React.FC = () => {
return (
<div className="relative w-full h-[500px] mb-3">
<img
src={hero}
alt="Hero Image"
className="absolute top-0 left-0 w-full h-full object-cover object-top z-0"
/>
<div className="relative z-10 container mx-auto px-4 py-5 h-[500px]">
{' '}
{/* Đảm bảo chiều cao của container */}
<div className="flex justify-start items-center h-full">
{' '}
{/* Căn giữa theo chiều dọc */}
<div className="lg:w-2/3 text-center lg:text-left">
<h1 className="font-pacifico text-[#E88F2A] mb-1.5 text-[35px] font-semibold">
nơi gắn kết sự kiện và trải nghiệm của bạn!
</h1>
<h1 className="text-[70px] font-bold text-white mb-4">EVORA</h1>
<h1 className="text-[40px] font-bold text-white text-xl mb-7">
ĐẶT SỰ KIỆN TRỰC TUYẾN
</h1>
<div className="w-full lg:w-[200px] lg:h-[70px] text-center py-3 bg-[#E88F2A] flex justify-center items-center font-bold text-white">
<div className="p-3 pl-[50px] pr-[50px] border-2 border-white">
<div className="flex justify-center items-center">
<NavLink to={path.CONTACT}>Xem thêm</NavLink>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
);
};

export default Banner;
37 changes: 37 additions & 0 deletions frontend/src/components/Button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React, { FC, memo } from 'react';

interface ButtonProps {
text: string;
textColor?: string;
bgColor?: string;
IcAfter?: React.ElementType;
IcBefor?: React.ElementType;
onClick?: () => void;
fullWidth?: boolean;
}

export const Button: FC<ButtonProps> = ({
text,
textColor = 'text-black',
bgColor = 'bg-white',
IcAfter,
onClick,
fullWidth = false,
IcBefor,
}) => {
return (
<button
type="button"
className={`py-2 px-4 ${textColor} ${bgColor} ${
fullWidth ? 'w-full' : ''
} outline-none rounded-md hover:underline flex items-center justify-center gap-1`}
onClick={onClick}
>
{IcBefor && <IcBefor />}
<span className="text-center">{text}</span>
{IcAfter && <IcAfter />}
</button>
);
};

export default memo(Button);
22 changes: 22 additions & 0 deletions frontend/src/components/ButtonForLogin.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
interface ButtonProps {
label: string;
type?: 'button' | 'submit' | 'reset';
onClick?: () => void;
}

const ButtonForLogin: React.FC<ButtonProps> = ({
label,
type = 'button',
onClick,
}) => {
return (
<button
type={type}
onClick={onClick}
className="w-full rounded bg-gradient-to-r from-yellow-500 via-orange-500 to-amber-700 px-6 py-2.5 text-lg font-medium text-white shadow-lg transition duration-150 ease-in-out hover:shadow-xl"
>
{label}
</button>
);
};
export default ButtonForLogin;
43 changes: 43 additions & 0 deletions frontend/src/components/Contact.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { text } from '../ultils/dataContact';
import React from 'react';

interface Contact {
text: string;
phone: string;
zalo: string;
}

const Contacts: React.FC = () => {
return (
<div className=" bg-[#FAF3EB] rounded-md shadow-md p-4 w-4/5 flex flex-col justify-center items-center gap-6">
<img
className="w-full h-48 object-contain"
src={text.image}
alt="thumbnail"
/>
<p className="">{text.content}</p>
<div className="flex items-center justify-around w-full">
{text.contact.map((item: Contact) => {
return (
<div
key={item.text}
className="flex flex-col items-center justify-center"
>
<span className="text-orange-600 text-[15px] font-bold ">
{item.text}
</span>
<span className="text-blue-900 text-[15px] font-bold">
{item.phone}
</span>
<span className="text-blue-900 text-[15px] font-bold">
{item.zalo}
</span>
</div>
);
})}
</div>
</div>
);
};

export default Contacts;
25 changes: 25 additions & 0 deletions frontend/src/components/InputField.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
interface InputFieldProps {
id: string;
label: string;
type: string;
}

const InputField: React.FC<InputFieldProps> = ({ id, label, type }) => {
return (
<div className="relative mb-6">
<input
type={type}
id={id}
className="peer block w-full rounded bg-transparent px-3 py-2.5 leading-6 border-b border-gray-300 outline-none focus:ring-2 focus:ring-primary dark:text-white dark:placeholder:text-neutral-300"
/>
<label
htmlFor={id}
className="absolute left-3 top-0 text-neutral-500 transition-all duration-200 dark:text-neutral-400 peer-placeholder-shown:translate-y-2 peer-placeholder-shown:scale-100 peer-focus:-translate-y-6 peer-focus:scale-75 peer-focus:text-primary"
>
{label}
</label>
</div>
);
};

export default InputField;
54 changes: 54 additions & 0 deletions frontend/src/components/Intro.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { text } from '../ultils/dataIntro';
import icons from '../ultils/icons';
import React, { memo } from 'react';

const { FaStar } = icons;
const stars = [1, 2, 3, 4, 5];

interface Statistic {
value: string;
name: string;
}

const Intro: React.FC = () => {
return (
<div className="w-4/5 bg-[#FAF3EB] rounded-md p-4 gap-4 shadow-md flex flex-col justify-center items-center">
<h3 className="font-bold text-lg">{text.title}</h3>
<p className="text-gray-800 text-center my-4 text-sm">
{text.description}
<span></span>
{text.description2}
</p>
<div className="flex items-center justify-around w-full">
{text.statistic.map((item: Statistic) => {
return (
<div
key={item.name}
className="flex flex-col justify-center items-center"
>
<h4 className="font-bold text-lg">{item.value}</h4>
<p className="text-gray-700">{item.name}</p>
</div>
);
})}
</div>
<h3 className="font-bold text-lg py-2">{text.price}</h3>
<div className="flex items-center justify-center gap-1">
{stars.map((item) => {
return (
<span key={item}>
<FaStar color="yellow" size={22} />
</span>
);
})}
</div>
<p className="text-gray-600 italic text-center">{text.comment}</p>
<span className="text-gray-700">{text.author}</span>
<h3 className="font-bold text-lg py-2">{text.question}</h3>
<p className="text-gray-800 text-center text-sm">{text.answer}</p>
<div className="h-12"></div>
</div>
);
};

export default memo(Intro);
Loading

0 comments on commit 0daaccb

Please sign in to comment.