Skip to content

Commit 9c28b1e

Browse files
committed
feat: 💄 improve project ui and code structure
1 parent 087ef7d commit 9c28b1e

25 files changed

+2988
-111
lines changed

README.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1-
# quick-pay
1+
# QuickPay Application
2+
23
My first TypeScript+React application
3-
<a href="https://sbk-quick-pay.netlify.app" target="_blank">View</a>
4+
<a href="https://quick-pay.soatov.uz" target="_blank">View</a>

index.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<title>Quick Pay</title>
88
</head>
99
<body>
10-
<div class="bg-primary" id="root"></div>
10+
<div id="root"></div>
1111
<script type="module" src="/src/main.tsx"></script>
1212
</body>
1313
</html>

package.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"preview": "vite preview"
1111
},
1212
"dependencies": {
13+
"classnames": "^2.5.1",
1314
"react": "^18.2.0",
1415
"react-dom": "^18.2.0",
1516
"react-router-dom": "^6.14.0"
@@ -23,8 +24,8 @@
2324
"eslint-plugin-react": "^7.32.2",
2425
"eslint-plugin-react-hooks": "^4.6.0",
2526
"eslint-plugin-react-refresh": "^0.3.4",
26-
"postcss": "^8.4.24",
27-
"tailwindcss": "^3.3.2",
27+
"postcss": "^8.4.38",
28+
"tailwindcss": "^3.4.4",
2829
"terser": "^5.31.0",
2930
"typescript": "^5.1.6",
3031
"vite": "^4.3.2",

public/vite.svg

-1
This file was deleted.

src/App.tsx

+13-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,22 @@
11
// components
22
import * as React from "react";
3-
import { Billing, Business, CTA, Clients, Contract, Footer, Header, Hero, Statistics, Testimonials } from "./components";
3+
import {
4+
Billing,
5+
Business,
6+
CTA,
7+
Clients,
8+
Contract,
9+
Footer,
10+
Header,
11+
Hero,
12+
Statistics,
13+
Testimonials,
14+
} from "./components";
415

516
const App: React.FC = (): JSX.Element => {
617
return (
718
<>
8-
<h1 className="visually-hidden">Quick Pay</h1>
19+
<h1 className="sr-only">Quick Pay</h1>
920
<Header />
1021
<main className="flex-grow-[1]">
1122
<Hero />

src/components/Billing.tsx

+7-5
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,26 @@
11
import * as React from "react";
2+
import cx from "classnames";
3+
24
import { apple, bill, google } from "../assets";
35
import { layout, styles } from "../constants/styles";
46

57
const Billing: React.FC = (): JSX.Element => {
68
return (
79
<section className={layout.section} id="services">
8-
<div className={`${styles.container} ${layout.wrapperReverse}`}>
9-
<div className={`${layout.sectionImage} ${layout.v2} relative`}>
10+
<div className={cx(styles.container, layout.wrapperReverse)}>
11+
<div className={cx("relative", layout.sectionImage, layout.v2)}>
1012
<img className="w-full h-auto" src={bill} alt="card" />
1113

1214
<div className="absolute z-[3] w-[50%] h-[50%] rounded-full top-0 blur-[900px] bg-lightWhite" />
1315
<div className="absolute z-[0] w-[50%] h-[50%] rounded-full bottom-0 bg-gradient-pink blur-[750px]" />
1416
</div>
15-
<div className={`${layout.sectionInfo}`}>
16-
<h2 className={`${styles.heading2} mb-5`}>
17+
<div className={layout.sectionInfo}>
18+
<h2 className={cx("mb-5", styles.heading2)}>
1719
Hisob-kitob va fakturialni
1820
<br className="hidden lg:block" />
1921
Osongina Boshqaring
2022
</h2>
21-
<p className={`${styles.paragraph} max-w-[600px] mb-4`}>
23+
<p className={cx("max-w-[600px] mb-4", styles.paragraph)}>
2224
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Natus dolorum nemo eius debitis labore repellat
2325
atque est ea harum dolor.
2426
</p>

src/components/Business.tsx

+7-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as React from "react";
2+
import cx from "classnames";
23

34
import { IFeatures } from "../interfaces";
45
import { features } from "../constants/constants";
@@ -9,20 +10,20 @@ import { Button, FeatureCard } from ".";
910
const Business: React.FC = (): JSX.Element => {
1011
return (
1112
<section className={layout.section} id="features">
12-
<div className={`${styles.container} ${layout.wrapper}`}>
13-
<div className={`${layout.sectionInfo}`}>
14-
<h2 className={`${styles.heading2} mb-5`}>
13+
<div className={cx(styles.container, layout.wrapper)}>
14+
<div className={layout.sectionInfo}>
15+
<h2 className={cx("mb-5", styles.heading2)}>
1516
Biznesingizni rivojlantiring
1617
<br className="hidden lg:block" />
1718
Biz bunda ko'mak beramiz!
1819
</h2>
19-
<p className={`${styles.paragraph} max-w-[550px] mb-4`}>
20+
<p className={cx("max-w-[550px] mb-4", styles.paragraph)}>
2021
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Voluptate dolore expedita beatae magnam corrupti
2122
facere totam quibusdam cupiditate, voluptas commodi.
2223
</p>
23-
<Button>Boshlash</Button>
24+
<Button children="Boshlash" />
2425
</div>
25-
<div className={`${layout.sectionImage} flex-col ${layout.v1}`}>
26+
<div className={cx("flex-col", layout.sectionImage, layout.v1)}>
2627
{features.map((feature: IFeatures) => (
2728
<FeatureCard key={feature.id} {...feature} />
2829
))}

src/components/Button.tsx

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
import * as React from "react";
2+
import cx from "classnames";
23

34
interface IProps {
45
children: string;
5-
styles?: string;
6+
className?: string;
67
}
78

8-
const Button: React.FC<IProps> = ({ children, styles = "" }): JSX.Element => {
9+
const Button: React.FC<IProps> = ({ children, className = "" }): JSX.Element => {
910
return (
1011
<button
11-
className={`py-3 px-6 flex font-montserrat font-medium text-[18px] bg-gradient-light-blue rounded-lg outline-none ${styles}`}
12+
className={cx(
13+
"py-2 px-5 flex font-montserrat font-medium text-[16px] bg-gradient-light-blue rounded-lg outline-none",
14+
className
15+
)}
1216
type="button"
1317
>
1418
{children}

src/components/CTA.tsx

+10-6
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,28 @@
11
import * as React from "react";
2+
import cx from "classnames";
23

34
import { styles } from "../constants/styles";
45
import { Button } from ".";
56

67
const CTA: React.FC = (): JSX.Element => {
78
return (
8-
<section className={`mb-12`} id="services">
9+
<section className="mb-12" id="services">
910
<div className={styles.container}>
1011
<div
11-
className={`${styles.flexCenter} flex-col text-center md:text-left lg:flex-row bg-gradient-black shadow-card bg-slate-800 py-6 lg:py-12 px-8 lg:px-16 rounded-[20px]`}
12+
className={cx(
13+
"flex-col text-center md:text-left lg:flex-row bg-gradient-black shadow-card bg-slate-800 py-6 lg:py-12 px-8 lg:px-16 rounded-[20px]",
14+
styles.flexCenter
15+
)}
1216
>
1317
<div className="flex-1 flex flex-col mr-0 lg:mr-10 mb-10 lg:mb-0">
14-
<h2 className={`${styles.heading2}`}>Xizmatlarni sinab ko'rish!</h2>
15-
<p className={`${styles.paragraph} max-w-[550px] mt-5`}>
18+
<h2 className={styles.heading2}>Xizmatlarni sinab ko'rish!</h2>
19+
<p className={cx("max-w-[550px] mt-5", styles.paragraph)}>
1620
Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ratione voluptates sequi.
1721
</p>
1822
</div>
1923

20-
<div className={`${styles.flexCenter}`}>
21-
<Button>Boshlash</Button>
24+
<div className={styles.flexCenter}>
25+
<Button children="Boshlash" />
2226
</div>
2327
</div>
2428
</div>

src/components/ClientCard.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ interface IProps {
66

77
const ClientCard: React.FC<IProps> = ({ logo }): JSX.Element => {
88
return (
9-
<div className={`max-w-[100px] md:max-w-[140px] lg:max-w-[220px]`}>
9+
<div className="max-w-[100px] md:max-w-[140px] lg:max-w-[220px]">
1010
<img className="w-full h-auto object-contain" src={logo} alt="client logo" />
1111
</div>
1212
);

src/components/Clients.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as React from "react";
2+
import cx from "classnames";
23

34
import { styles } from "../constants/styles";
45
import { clients } from "../constants/constants";
@@ -7,8 +8,8 @@ import { ClientCard } from ".";
78

89
const Clients: React.FC = (): JSX.Element => {
910
return (
10-
<section className={`${styles.flexCenter} ${styles.container} my-4`} id="clients">
11-
<div className={`flex justify-center items-center lg:justify-between gap-[50px] flex-wrap w-full`}>
11+
<section className={cx("my-4", styles.flexCenter, styles.container)} id="clients">
12+
<div className="flex justify-center items-center lg:justify-between gap-[50px] flex-wrap w-full">
1213
{clients.map(client => (
1314
<ClientCard key={client.id} {...client} />
1415
))}

src/components/Contract.tsx

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as React from "react";
2+
import cx from "classnames";
23

34
import { card } from "../assets";
45
import { layout, styles } from "../constants/styles";
@@ -8,20 +9,20 @@ import { Button } from ".";
89
const Contract: React.FC = (): JSX.Element => {
910
return (
1011
<section className={layout.section} id="product">
11-
<div className={`${styles.container} ${layout.wrapper}`}>
12-
<div className={`${layout.sectionInfo}`}>
13-
<h2 className={`${styles.heading2} mb-5`}>
12+
<div className={cx(styles.container, layout.wrapper)}>
13+
<div className={layout.sectionInfo}>
14+
<h2 className={cx("mb-5", styles.heading2)}>
1415
Bir necha oson qadamda muqobil
1516
<br className="hidden lg:block" />
1617
shartnomaga ega bo'ling
1718
</h2>
18-
<p className={`${styles.paragraph} max-w-[600px] mb-4`}>
19+
<p className={cx("max-w-[600px] mb-4", styles.paragraph)}>
1920
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Natus dolorum nemo eius debitis labore repellat
2021
atque est ea harum dolor.
2122
</p>
2223
<Button>Boshlash</Button>
2324
</div>
24-
<div className={`${layout.sectionImage} ${layout.v1}`}>
25+
<div className={cx(layout.sectionImage, layout.v1)}>
2526
<img className="w-full h-auto" src={card} alt="card" />
2627
</div>
2728
</div>

src/components/FeatureCard.tsx

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
import * as React from "react";
2+
import cx from "classnames";
23

34
import { IFeatures } from "../interfaces";
45
import { styles } from "../constants/styles";
56

67
const FeatureCard: React.FC<IFeatures> = ({ icon, title, content }): JSX.Element => {
78
return (
8-
<div
9-
className={`flex flex-row p-6 rounded-[20px] cursor-pointer [&:not(:last-child)]:mb-6 hover:shadow-card transition-all hover:bg-gradient-black duration-300`}
10-
>
11-
<div className={`w-[64px] h-[64px] mr-3 rounded-full ${styles.flexCenter} bg-lightBlue`}>
9+
<div className="flex flex-row p-6 rounded-[20px] cursor-pointer [&:not(:last-child)]:mb-6 hover:shadow-card transition-all hover:bg-gradient-black duration-300">
10+
<div className={cx("w-[64px] h-[64px] mr-3 rounded-full bg-lightBlue", styles.flexCenter)}>
1211
<img className="w-[50%] h-[50%] object-contain" src={icon} alt={title} />
1312
</div>
1413

src/components/FeedbackCard.tsx

+10-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import * as React from "react";
2+
import cx from "classnames";
3+
24
import { quotes } from "../assets";
5+
import { styles } from "../constants/styles";
36

47
interface IProps {
58
content: string;
@@ -17,15 +20,17 @@ const FeedbackCard: React.FC<IProps> = ({ content, name, title }): JSX.Element =
1720
return (
1821
<div className="flex justify-between flex-col cursor-pointer px-10 py-12 mr-0 sm:[&:not(:last-child)]:mr-5 md:[&:not(:last-child)]:mr-10 rounded-[20px] max-w-[370px] hover:bg-gradient-black hover:shadow-card transition-all duration-300">
1922
<img className="w-[42px] h-auto object-contain" src={quotes} alt="quotes" />
20-
<p className={`font-montserrat font-normal text-[18px] leading-[32px] text-white my-10`}>{content}</p>
23+
<p className={cx("font-montserrat font-normal leading-[1.5] text-white my-10", styles.paragraph)}>{content}</p>
2124

2225
<div className="flex flex-row">
23-
<div className="w-[50px] h-[50px] mr-4 flex justify-center items-center bg-gradient-secondary rounded-full ">
24-
<p className="font-montserrat font-semibold text-[22px] bg-gradient-black text-transparent bg-clip-text">{splitter(name)}</p>
26+
<div className="size-[50px] mr-4 flex justify-center items-center bg-gradient-secondary rounded-full">
27+
<p className="font-montserrat font-semibold text-[20px] bg-gradient-black text-transparent bg-clip-text">
28+
{splitter(name)}
29+
</p>
2530
</div>
2631
<div className="font-montserrat flex flex-col">
27-
<h4 className="font-semibold text-[20px] leading-[32px] text-white">{name}</h4>
28-
<p className=" font-normal text-[16px] leading-[24px] text-lightWhite">{title}</p>
32+
<h4 className="font-semibold text-[22px] leading-[1.5] text-white">{name}</h4>
33+
<p className=" font-normal text-[16px] leading-[1.5] text-lightWhite">{title}</p>
2934
</div>
3035
</div>
3136
</div>

src/components/Footer.tsx

+7-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as React from "react";
2+
import cx from "classnames";
23

34
import { footerLinks, socials } from "../constants/constants";
45
import { styles } from "../constants/styles";
@@ -8,11 +9,11 @@ import { FooterLinks } from ".";
89
const Footer: React.FC = (): JSX.Element => {
910
return (
1011
<footer className="py-6 lg:py-9">
11-
<div className={`${styles.container} ${styles.flexCenter} flex-col`}>
12-
<div className={`${styles.flexCenter} flex-col lg:flex-row w-full mb-4`}>
13-
<div className={`flex-1 flex-col justify-start mr-10`}>
12+
<div className={cx("flex-col", styles.container, styles.flexCenter)}>
13+
<div className={cx("flex-col lg:flex-row w-full mb-4", styles.flexCenter)}>
14+
<div className="flex-1 flex-col justify-start mr-10">
1415
<img className="w-[250px] h-auto mb-4" src={logo} alt="quick-pay logo" />
15-
<p className={`${styles.paragraph} max-w-[370px]`}>
16+
<p className={cx("max-w-[370px]", styles.paragraph)}>
1617
To'lovlarni oson, ishonchli va xavfsiz qilishning yangi usuli.
1718
</p>
1819
</div>
@@ -24,15 +25,15 @@ const Footer: React.FC = (): JSX.Element => {
2425
</div>
2526
</div>
2627

27-
<div className={`w-full ${styles.flexBetween} flex-col lg:flex-row border-t-[1px] border-top-[#3f3e45]`}>
28+
<div className={cx("w-full flex-col lg:flex-row border-t-[1px] border-top-[#3f3e45]", styles.flexBetween)}>
2829
<p className="font-montserrat font-normal pt-6 text-center text-[18px] leading-[27px] text-white">
2930
©️Copyright 2023 QuickPay. All Rights Reserved
3031
</p>
3132

3233
<div className="flex items-center flex-row mt-6 lg:mt-0">
3334
{socials.map(social => (
3435
<a className="[&:not(:last-child)]:mr-3" href={social.link} target="_blank" key={social.id}>
35-
<img className={`w-[21px] h-auto object-contain`} src={social.icon} alt="social icon" key={social.id} />
36+
<img className="w-[21px] h-auto object-contain" src={social.icon} alt="social icon" key={social.id} />
3637
</a>
3738
))}
3839
</div>

src/components/FooterLinks.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as React from "react";
2+
23
import { IFooterLinks } from "../interfaces";
34

45
const FooterLinks: React.FC<IFooterLinks> = ({ title, links }): JSX.Element => {

src/components/Header.tsx

+11-9
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,38 @@
11
import * as React from "react";
2-
import { useState } from "react";
2+
import cx from "classnames";
33

44
import { styles } from "../constants/styles";
55
import { close, logo, menu } from "../assets";
66
import { navLinks } from "../constants/constants";
77

88
const Header: React.FC = (): JSX.Element => {
9-
const [isNavOpen, setIsNavOpen] = useState<boolean>(false);
10-
const [isActive, setIsActive] = useState<string>("#");
9+
const [isNavOpen, setIsNavOpen] = React.useState<boolean>(false);
10+
const [isActive, setIsActive] = React.useState<string>("#");
1111

1212
const handleToggleNav = (): void => setIsNavOpen(prev => !prev);
1313

1414
return (
15-
<header className="bg-primary py-6 z-[100] sticky top-0">
16-
<div className={styles.flexBetween + " " + styles.container}>
15+
<header className="bg-primary py-3 z-[100] sticky top-0">
16+
<div className={cx(styles.flexBetween, styles.container)}>
1717
<img className="w-[130px] cursor-pointer" src={logo} alt="logo quick-pay" />
1818

1919
<button className="sm:hidden inline-flex" onClick={handleToggleNav}>
2020
<img className="w-[24px] h-[24px] object-contain" src={isNavOpen ? close : menu} alt="nav toggler" />
2121
</button>
2222

2323
<nav
24-
className={`${
24+
className={cx(
25+
"bg-primary sm:bg-transparent w-full sm:w-auto left-0 absolute sm:static top-[89px] sm:block sidebar py-4 px-3 sm:py-0 sm:px-0",
2526
isNavOpen ? "block" : "hidden"
26-
} bg-primary sm:bg-transparent w-full sm:w-auto left-0 absolute sm:static top-[89px] sm:block sidebar py-4 px-3 sm:py-0 sm:px-0`}
27+
)}
2728
>
2829
<ul className="list-none flex w-full sm:w-auto flex-wrap sm:flex-nowrap justify-center sm:justify-end">
2930
{navLinks.map(({ title, path }) => (
3031
<li
31-
className={`${
32+
className={cx(
33+
"sm:[&:not(:last-child)]:mr-9 mx-2 font-montserrat font-medium sm:font-normal hover:text-secondary transition-all duration-500",
3234
isActive === path ? "text-white" : "text-lightWhite"
33-
} sm:[&:not(:last-child)]:mr-9 mx-2 font-montserrat font-medium sm:font-normal hover:text-secondary transition-all duration-500`}
35+
)}
3436
key={path}
3537
>
3638
<a className="text-inherit" href={path} onClick={(): void => setIsActive(path)}>

0 commit comments

Comments
 (0)