Skip to content

Commit f0775f0

Browse files
authored
Merge pull request #2 from purwadhikafullstack/homepage
Homepage
2 parents c10f808 + 934ae26 commit f0775f0

26 files changed

+1507
-36
lines changed

apps/api/.env.development

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
NODE_ENV=development
22
PORT=8000
3-
DATABASE_URL="mysql://root@localhost:3306/mydb"
3+
DATABASE_URL="mysql://root:Redline-2@localhost:3306/grocery"

apps/api/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"devDependencies": {
2626
"@types/cors": "^2.8.17",
2727
"@types/express": "^4.17.21",
28+
"dotenv-cli": "^7.4.2",
2829
"prisma": "^5.7.1",
2930
"tsconfig-paths": "^4.2.0"
3031
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
Warnings:
3+
4+
- You are about to drop the `samples` table. If the table is not empty, all the data it contains will be lost.
5+
6+
*/
7+
-- DropTable
8+
DROP TABLE `samples`;
9+
10+
-- CreateTable
11+
CREATE TABLE `User` (
12+
`id` INTEGER NOT NULL AUTO_INCREMENT,
13+
`email` VARCHAR(191) NOT NULL,
14+
`password` VARCHAR(191) NOT NULL,
15+
16+
UNIQUE INDEX `User_email_key`(`email`),
17+
PRIMARY KEY (`id`)
18+
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
19+
20+
-- CreateTable
21+
CREATE TABLE `Store` (
22+
`id` INTEGER NOT NULL AUTO_INCREMENT,
23+
`name` VARCHAR(191) NOT NULL,
24+
`location` VARCHAR(191) NOT NULL,
25+
26+
PRIMARY KEY (`id`)
27+
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
28+
29+
-- CreateTable
30+
CREATE TABLE `Product` (
31+
`id` INTEGER NOT NULL AUTO_INCREMENT,
32+
`name` VARCHAR(191) NOT NULL,
33+
`price` DOUBLE NOT NULL,
34+
`storeId` INTEGER NOT NULL,
35+
36+
PRIMARY KEY (`id`)
37+
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
38+
39+
-- CreateTable
40+
CREATE TABLE `Order` (
41+
`id` INTEGER NOT NULL AUTO_INCREMENT,
42+
`userId` INTEGER NOT NULL,
43+
`storeId` INTEGER NOT NULL,
44+
`productId` INTEGER NOT NULL,
45+
`status` VARCHAR(191) NOT NULL,
46+
`createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
47+
48+
PRIMARY KEY (`id`)
49+
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
50+
51+
-- AddForeignKey
52+
ALTER TABLE `Product` ADD CONSTRAINT `Product_storeId_fkey` FOREIGN KEY (`storeId`) REFERENCES `Store`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
53+
54+
-- AddForeignKey
55+
ALTER TABLE `Order` ADD CONSTRAINT `Order_userId_fkey` FOREIGN KEY (`userId`) REFERENCES `User`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
56+
57+
-- AddForeignKey
58+
ALTER TABLE `Order` ADD CONSTRAINT `Order_storeId_fkey` FOREIGN KEY (`storeId`) REFERENCES `Store`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
59+
60+
-- AddForeignKey
61+
ALTER TABLE `Order` ADD CONSTRAINT `Order_productId_fkey` FOREIGN KEY (`productId`) REFERENCES `Product`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;

apps/api/prisma/schema.prisma

+31-5
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,38 @@ datasource db {
1010
url = env("DATABASE_URL")
1111
}
1212

13-
model Sample {
13+
model User {
14+
id Int @id @default(autoincrement())
15+
email String @unique
16+
password String
17+
orders Order[]
18+
}
19+
20+
model Store {
1421
id Int @id @default(autoincrement())
1522
name String
16-
code String @unique
17-
createdAt DateTime @default(now())
18-
updatedAt DateTime @updatedAt
23+
location String
24+
products Product[]
25+
orders Order[]
26+
}
1927

20-
@@map("samples") // if you want to use snake_case format
28+
model Product {
29+
id Int @id @default(autoincrement())
30+
name String
31+
price Float
32+
storeId Int
33+
store Store @relation(fields: [storeId], references: [id])
34+
orders Order[]
35+
}
36+
37+
model Order {
38+
id Int @id @default(autoincrement())
39+
userId Int
40+
user User @relation(fields: [userId], references: [id])
41+
storeId Int
42+
store Store @relation(fields: [storeId], references: [id])
43+
productId Int
44+
product Product @relation(fields: [productId], references: [id])
45+
status String
46+
createdAt DateTime @default(now())
2147
}

apps/web/package.json

+5-2
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,21 @@
1010
"test": "npx cypress verify & cypress run --component"
1111
},
1212
"dependencies": {
13+
"cross-env": "^7.0.3",
1314
"next": "14.0.4",
1415
"react": "^18",
15-
"react-dom": "^18",
16-
"cross-env": "^7.0.3"
16+
"react-dom": "^18"
1717
},
1818
"devDependencies": {
1919
"@types/node": "^20",
2020
"@types/react": "^18",
2121
"@types/react-dom": "^18",
22+
"autoprefixer": "^10.4.20",
2223
"cypress": "^13.6.2",
2324
"eslint": "^8",
2425
"eslint-config-next": "14.0.4",
26+
"postcss": "^8.4.41",
27+
"tailwindcss": "^3.4.9",
2528
"typescript": "^5"
2629
}
2730
}

apps/web/postcss.config.js

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module.exports = {
2+
plugins: {
3+
tailwindcss: {},
4+
autoprefixer: {},
5+
},
6+
}

apps/web/public/images/avatar.png

7.01 KB
Loading

apps/web/public/images/joyland.png

328 KB
Loading

apps/web/public/images/lalala.jpg

226 KB
Loading

apps/web/public/images/logo-1.png

45.3 KB
Loading

apps/web/public/images/logo.png

9.76 KB
Loading

apps/web/public/images/pespor.png

120 KB
Loading
58 KB
Binary file not shown.

apps/web/public/images/wtf.png

629 KB
Loading

apps/web/src/app/globals.css

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
@tailwind base;
2+
@tailwind components;
3+
@tailwind utilities;
4+
15
:root {
26
--max-width: 1100px;
37
--border-radius: 12px;

apps/web/src/app/home/page.tsx

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
'use client';
2+
import React from 'react';
3+
import Carousel from '@/components/HomePage/carousel';
4+
import Footer from '@/components/HomePage/Footer';
5+
import Navbar from '@/components/HomePage/Navbar';
6+
import ProductCard from '@/components/HomePage/ProductCard';
7+
8+
const page = () => {
9+
const images = [
10+
'/images/pespor.png',
11+
'/images/wtf.png',
12+
'/images/joyland.png',
13+
'/images/synchronize.webp',
14+
'/images/lalala.jpg',
15+
];
16+
17+
const handleAddToCart = () => {
18+
alert('Product added to cart!');
19+
};
20+
21+
return (
22+
<div className="overflow-x-hidden h-screen bg-white">
23+
<div className="z-10">
24+
<Navbar />
25+
</div>
26+
<div className="justify-center flex mt-7">
27+
<Carousel images={images} />
28+
</div>
29+
<div className="p-8 grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
30+
<ProductCard
31+
imageUrl="https://via.placeholder.com/300"
32+
name="Fresh Apples"
33+
price="20.000"
34+
unit="1kg"
35+
onAddToCart={handleAddToCart}
36+
/>
37+
<ProductCard
38+
imageUrl="https://via.placeholder.com/300"
39+
name="Organic Bananas"
40+
price="40.000"
41+
unit="1kg"
42+
onAddToCart={handleAddToCart}
43+
/>
44+
<ProductCard
45+
imageUrl="https://via.placeholder.com/300"
46+
name="Red Tomatoes"
47+
price="20.000"
48+
unit="500g"
49+
onAddToCart={handleAddToCart}
50+
/>
51+
<ProductCard
52+
imageUrl="https://via.placeholder.com/300"
53+
name="Red Tomatoes"
54+
price="20.000"
55+
unit="500g"
56+
onAddToCart={handleAddToCart}
57+
/>
58+
<ProductCard
59+
imageUrl="https://via.placeholder.com/300"
60+
name="Red Tomatoes"
61+
price="20.000"
62+
unit="500g"
63+
onAddToCart={handleAddToCart}
64+
/>
65+
<ProductCard
66+
imageUrl="https://via.placeholder.com/300"
67+
name="Red Tomatoes"
68+
price="20.000"
69+
unit="500g"
70+
onAddToCart={handleAddToCart}
71+
/>
72+
<ProductCard
73+
imageUrl="https://via.placeholder.com/300"
74+
name="Red Tomatoes"
75+
price="20.000"
76+
unit="500g"
77+
onAddToCart={handleAddToCart}
78+
/>
79+
<ProductCard
80+
imageUrl="https://via.placeholder.com/300"
81+
name="Red Tomatoes"
82+
price="20.000"
83+
unit="500g"
84+
onAddToCart={handleAddToCart}
85+
/>
86+
</div>
87+
<div>
88+
<Footer />
89+
</div>
90+
</div>
91+
);
92+
};
93+
94+
export default page;

apps/web/src/app/layout.tsx

+1-7
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import type { Metadata } from 'next';
22
import { Inter } from 'next/font/google';
33
import './globals.css';
4-
import { Header } from '@/components/Header';
5-
import { Footer } from '@/components/Footer';
64

75
const inter = Inter({ subsets: ['latin'] });
86

@@ -18,11 +16,7 @@ export default function RootLayout({
1816
}) {
1917
return (
2018
<html lang="en">
21-
<body className={inter.className}>
22-
<Header />
23-
{children}
24-
<Footer />
25-
</body>
19+
<body className={inter.className}>{children}</body>
2620
</html>
2721
);
2822
}

apps/web/src/components/Footer.tsx

-3
This file was deleted.

apps/web/src/components/Header.tsx

-3
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
'use client';
2+
import React, { useState } from 'react';
3+
4+
interface CarouselProps {
5+
images: string[];
6+
}
7+
8+
const Carousel: React.FC<CarouselProps> = ({ images }) => {
9+
const [currentIndex, setCurrentIndex] = useState(0);
10+
11+
const prevSlide = () => {
12+
const isFirstSlide = currentIndex === 0;
13+
const newIndex = isFirstSlide ? images.length - 1 : currentIndex - 1;
14+
setCurrentIndex(newIndex);
15+
};
16+
17+
const nextSlide = () => {
18+
const isLastSlide = currentIndex === images.length - 1;
19+
const newIndex = isLastSlide ? 0 : currentIndex + 1;
20+
setCurrentIndex(newIndex);
21+
};
22+
23+
return (
24+
<div className="relative w-[90%] justify-center" data-carousel="slide">
25+
<div className="space-y-5 sm:space-y-7 mb-3 pl-2 text-primary text-left sm:text-left lg:text-left">
26+
<h1 className="text-4xl text-orange-600 sm:text-2xl lg:text-3xl font-bold">
27+
Lorem Ipsum
28+
</h1>
29+
</div>
30+
<div className="relative h-56 overflow-hidden rounded-lg md:h-96 lg:h-64">
31+
{images.map((image, index) => (
32+
<div
33+
key={index}
34+
className={`absolute inset-0 transition-opacity duration-700 ease-in-out ${
35+
index === currentIndex ? 'opacity-100' : 'opacity-0'
36+
}`}
37+
>
38+
<img
39+
src={image}
40+
className="object-cover w-full h-full"
41+
alt={`Slide ${index + 1}`}
42+
/>
43+
</div>
44+
))}
45+
</div>
46+
47+
<div className="absolute flex -translate-x-1/2 bottom-5 left-1/2 space-x-3">
48+
{images.map((_, index) => (
49+
<button
50+
key={index}
51+
type="button"
52+
className={`w-3 h-3 rounded-full ${
53+
index === currentIndex ? 'bg-white' : 'bg-gray-300'
54+
}`}
55+
onClick={() => setCurrentIndex(index)}
56+
></button>
57+
))}
58+
</div>
59+
60+
<button
61+
type="button"
62+
className="absolute top-3 left-0 flex items-center justify-center h-full px-4 cursor-pointer group focus:outline-none"
63+
onClick={prevSlide}
64+
>
65+
<span className="inline-flex items-center justify-center w-10 h-10 rounded-full bg-white/30 dark:bg-gray-800/30 group-hover:bg-white/50 dark:group-hover:bg-gray-800/60 group-focus:ring-4 group-focus:ring-white dark:group-focus:ring-gray-800/70 group-focus:outline-none">
66+
<svg
67+
className="w-4 h-4 text-white dark:text-gray-800"
68+
aria-hidden="true"
69+
xmlns="http://www.w3.org/2000/svg"
70+
fill="none"
71+
viewBox="0 0 6 10"
72+
>
73+
<path
74+
stroke="currentColor"
75+
strokeLinecap="round"
76+
strokeLinejoin="round"
77+
strokeWidth="2"
78+
d="M5 1 1 5l4 4"
79+
/>
80+
</svg>
81+
<span className="sr-only">Previous</span>
82+
</span>
83+
</button>
84+
<button
85+
type="button"
86+
className="absolute top-3 right-0 flex items-center justify-center h-full px-4 cursor-pointer group focus:outline-none"
87+
onClick={nextSlide}
88+
>
89+
<span className="inline-flex items-center justify-center w-10 h-10 rounded-full bg-white/30 dark:bg-gray-800/30 group-hover:bg-white/50 dark:group-hover:bg-gray-800/60 group-focus:ring-4 group-focus:ring-white dark:group-focus:ring-gray-800/70 group-focus:outline-none">
90+
<svg
91+
className="w-4 h-4 text-white dark:text-gray-800"
92+
aria-hidden="true"
93+
xmlns="http://www.w3.org/2000/svg"
94+
fill="none"
95+
viewBox="0 0 6 10"
96+
>
97+
<path
98+
stroke="currentColor"
99+
strokeLinecap="round"
100+
strokeLinejoin="round"
101+
strokeWidth="2"
102+
d="m1 9 4-4-4-4"
103+
/>
104+
</svg>
105+
<span className="sr-only">Next</span>
106+
</span>
107+
</button>
108+
</div>
109+
);
110+
};
111+
112+
export default Carousel;

0 commit comments

Comments
 (0)