Skip to content

Commit b7d4a47

Browse files
committed
feat: implement home page UI components
Signed-off-by: kshitij79 <[email protected]> refactor: incorporated pr review comments Signed-off-by: kshitij79 <[email protected]>
1 parent 5b390d9 commit b7d4a47

13 files changed

+279
-3
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import React from "react";
2+
import { ActivityItem } from "../../src/app/home/ActivityItem";
3+
4+
describe("ActivityItem Component", () => {
5+
it("displays restaurant name and amount correctly", () => {
6+
cy.mount(
7+
<ActivityItem title="Restaurant XY" amount={100} status="Received" />,
8+
);
9+
cy.contains("Restaurant XY").should("exist");
10+
cy.contains("+100").should("exist");
11+
});
12+
13+
it("shows status correctly", () => {
14+
cy.mount(<ActivityItem title="Greenstand" amount={-200} status="Sent" />);
15+
cy.contains("Sent").should("exist");
16+
cy.contains("-200").should("exist");
17+
});
18+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import React from "react";
2+
import HomeContent from "../../src/app/home/page";
3+
4+
describe("HomeContent Component", () => {
5+
it("renders TokenBalance and WalletBalance", () => {
6+
cy.mount(<HomeContent />);
7+
cy.contains("Tokens").should("exist");
8+
cy.contains("Wallet").should("exist");
9+
});
10+
11+
it("renders RecentActivity", () => {
12+
cy.mount(<HomeContent />);
13+
cy.contains("Recent Activity").should("exist");
14+
});
15+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import React from "react";
2+
import { RecentActivity } from "../../src/app/home/RecentActivity";
3+
4+
const activityData = [
5+
{ title: "Restaurant XY", amount: 100, status: "Received" },
6+
];
7+
8+
describe("RecentActivity Component", () => {
9+
it("displays title and activity items", () => {
10+
cy.mount(<RecentActivity activityData={activityData} />);
11+
cy.contains("Recent Activity").should("exist");
12+
cy.contains("Restaurant XY").should("exist");
13+
});
14+
15+
it("has a clickable View All button", () => {
16+
cy.mount(<RecentActivity activityData={activityData} />);
17+
cy.contains("View all").should("exist").click();
18+
});
19+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import React from "react";
2+
import { TokenBalance } from "../../src/app/home/TokenBalance";
3+
4+
describe("TokenBalance Component", () => {
5+
it("displays correct token count", () => {
6+
cy.mount(<TokenBalance tokenCount={1000} />);
7+
cy.contains("Tokens").should("exist");
8+
cy.contains("1000").should("exist");
9+
});
10+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import React from "react";
2+
import { WalletBalance } from "../../src/app/home/WalletBalance";
3+
4+
describe("WalletBalance Component", () => {
5+
it("displays correct wallet amount", () => {
6+
cy.mount(<WalletBalance walletAmount={500} />);
7+
cy.contains("Wallet").should("exist");
8+
cy.contains("500").should("exist");
9+
});
10+
});
+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
"use client";
2+
3+
import * as React from "react";
4+
import {
5+
Typography,
6+
Box,
7+
Card,
8+
CardContent,
9+
Avatar,
10+
Stack,
11+
} from "@mui/material";
12+
13+
// Function to extract initials from restaurant name
14+
const getInitials = (name: string) => {
15+
const words = name.split(" ");
16+
return words.length > 1 ? words[0][0] + words[1][0] : words[0][0];
17+
};
18+
19+
export function ActivityItem({
20+
title,
21+
amount,
22+
status,
23+
}: {
24+
title: string;
25+
amount: number;
26+
status: string;
27+
}) {
28+
return (
29+
<Card sx={{ my: 0.5, p: 1, flex: 1, minWidth: "80%" }}>
30+
<CardContent sx={{ py: 0.5, "&:last-child": { pb: 0.5 } }}>
31+
<Stack direction="row" spacing={2} alignItems="center">
32+
{/* Circular Avatar Icon with Initials */}
33+
<Avatar sx={{ width: 40, height: 40 }}>{getInitials(title)}</Avatar>
34+
35+
{/* Restaurant Name & Status */}
36+
<Box sx={{ flexGrow: 1 }}>
37+
<Typography variant="h6" color="textSecondary">
38+
{title}
39+
</Typography>
40+
<Typography variant="caption" color="textSecondary">
41+
{status}
42+
</Typography>
43+
</Box>
44+
45+
{/* Amount on Right Side */}
46+
<Typography
47+
variant="h6"
48+
color={
49+
amount > 0 && status !== "Pending" ? "green" : "textSecondary"
50+
}>
51+
{status === "Pending" ? "" : amount > 0 ? "+" : ""}
52+
{amount}
53+
</Typography>
54+
</Stack>
55+
</CardContent>
56+
</Card>
57+
);
58+
}
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
"use client";
2+
3+
import * as React from "react";
4+
import { Box } from "@mui/material";
5+
import { ActivityItem } from "./ActivityItem";
6+
7+
export function ActivityList({ activityData }: { activityData: any[] }) {
8+
return (
9+
<Box>
10+
{activityData.map((item, index) => (
11+
<ActivityItem
12+
key={index}
13+
title={item.title}
14+
amount={item.amount}
15+
status={item.status}
16+
/>
17+
))}
18+
</Box>
19+
);
20+
}
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
"use client";
2+
3+
import * as React from "react";
4+
import { Typography, Box } from "@mui/material";
5+
import { ActivityList } from "./ActivityList";
6+
7+
export function RecentActivity({ activityData }: { activityData: any[] }) {
8+
return (
9+
<Box sx={{ mt: 4 }}>
10+
<Box display="flex" justifyContent="space-between">
11+
<Typography variant="h6">Recent Activity</Typography>
12+
{/* Make view all align with activity title */}
13+
<Typography
14+
variant="body2"
15+
color="primary"
16+
sx={{
17+
cursor: "pointer",
18+
textDecoration: "underline",
19+
alignSelf: "center",
20+
}}>
21+
View all
22+
</Typography>
23+
</Box>
24+
<ActivityList activityData={activityData} />
25+
</Box>
26+
);
27+
}
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
"use client";
2+
3+
import * as React from "react";
4+
import TollOutlinedIcon from "@mui/icons-material/TollOutlined";
5+
import { CustomBalanceCard } from "@/components/common/CustomBalanceCard";
6+
7+
export function TokenBalance({ tokenCount }: { tokenCount: number }) {
8+
return (
9+
<CustomBalanceCard
10+
icon={<TollOutlinedIcon sx={{ color: "green" }} />}
11+
label="Tokens"
12+
value={tokenCount}
13+
/>
14+
);
15+
}
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
"use client";
2+
3+
import * as React from "react";
4+
import AccountBalanceWalletIcon from "@mui/icons-material/AccountBalanceWalletOutlined";
5+
import { CustomBalanceCard } from "@/components/common/CustomBalanceCard";
6+
7+
export function WalletBalance({ walletAmount }: { walletAmount: number }) {
8+
return (
9+
<CustomBalanceCard
10+
icon={<AccountBalanceWalletIcon />}
11+
label="Wallet"
12+
value={walletAmount}
13+
/>
14+
);
15+
}

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

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
"use client";
2+
3+
import * as React from "react";
4+
import { Container, Box } from "@mui/material";
5+
import { TokenBalance } from "./TokenBalance";
6+
import { WalletBalance } from "./WalletBalance";
7+
import { RecentActivity } from "./RecentActivity";
8+
9+
const activityData = [
10+
{ title: "Restaurant XY", amount: 200, status: "Pending" },
11+
{ title: "Restaurant XY", amount: 100, status: "Received" },
12+
{ title: "Greenstand", amount: -200, status: "Sent" },
13+
];
14+
15+
export default function Home() {
16+
return (
17+
<Container maxWidth="lg" sx={{ mt: 1 }}>
18+
<Box
19+
display="flex"
20+
flexDirection="row"
21+
gap={4}
22+
justifyContent="center"
23+
alignItems="center"
24+
width="100%">
25+
<TokenBalance tokenCount={1000} />
26+
<WalletBalance walletAmount={2} />
27+
</Box>
28+
<RecentActivity activityData={activityData} />
29+
</Container>
30+
);
31+
}

apps/web/src/app/page.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import * as React from "react";
44
import { Container, Box, Typography } from "@mui/material";
5+
import { default as Homepage } from "./home/page";
56

67
export default function Home() {
78
return (
@@ -15,9 +16,8 @@ export default function Home() {
1516
justifyContent: "center",
1617
alignItems: "center",
1718
}}>
18-
<Typography variant="h4" component="h1" sx={{ mb: 2 }}>
19-
Home Page
20-
</Typography>
19+
<Typography variant="h4" component="h1" sx={{ mb: 2 }}></Typography>
20+
<Homepage />
2121
</Box>
2222
</Container>
2323
</>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
"use client";
2+
3+
import * as React from "react";
4+
import { Typography, Card, CardContent, Stack, Box } from "@mui/material";
5+
6+
interface CustomBalanceCardProps {
7+
icon: React.ReactNode;
8+
label: string;
9+
value: number;
10+
}
11+
12+
export function CustomBalanceCard({
13+
icon,
14+
label,
15+
value,
16+
}: CustomBalanceCardProps) {
17+
return (
18+
<Card
19+
sx={{
20+
flex: 1,
21+
minWidth: "45%",
22+
display: "flex",
23+
flexDirection: "column",
24+
}}>
25+
<CardContent>
26+
<Stack direction="row" alignItems="center" spacing={1}>
27+
{icon}
28+
<Typography variant="h6" color="textSecondary">
29+
{label}
30+
</Typography>
31+
</Stack>
32+
<Box display="flex" justifyContent="flex-end">
33+
<Typography variant="h4">{value}</Typography>
34+
</Box>
35+
</CardContent>
36+
</Card>
37+
);
38+
}

0 commit comments

Comments
 (0)