Skip to content

Commit

Permalink
Merge pull request #6 from snehasharma1111/master
Browse files Browse the repository at this point in the history
Added contributions
  • Loading branch information
akshatmittal61 authored Jan 3, 2025
2 parents 665cdde + 8976f05 commit 9f43d47
Show file tree
Hide file tree
Showing 11 changed files with 235 additions and 6 deletions.
94 changes: 94 additions & 0 deletions components/Groups/contributions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { fallbackAssets } from "@/constants";
import { useStore } from "@/hooks";
import { Avatar, Typography } from "@/library";
import { IShare } from "@/types";
import { stylesConfig } from "@/utils";
import React from "react";
import styles from "./styles.module.scss";

interface IGroupContributionsProps {
shares: Array<IShare>;
}

const classes = stylesConfig(styles, "group-contributions");

const GroupContributions: React.FC<IGroupContributionsProps> = ({ shares }) => {
const { accentColor, theme } = useStore();
return (
<div className={classes("")}>
<div className={classes("-bar")}>
{shares.map((share) => (
<div
className={classes("-bar__item")}
key={`group-contributions-bar-${share.user.id}`}
style={{
width: `${share.percentage}%`,
backgroundColor: `rgba(${accentColor}, ${share.opacity})`,
}}
>
<div className={classes("-bar__item--user")}>
<Typography
className={classes("-bar__item--user__name")}
size="s"
>
{share.user.name ||
share.user.email.slice(0, 7)}
</Typography>
<Typography
className={classes("-bar__item--user__share")}
size="xs"
>
{share.percentage}%
</Typography>
</div>
</div>
))}
</div>
<div className={classes("-cards")}>
{shares.map((record, recId) => (
<div
key={`owed-record-person-${recId}`}
className={classes("-person", "-person--block")}
style={{
backgroundColor: `rgba(${accentColor}, ${record.opacity})`,
}}
>
<div
className={classes("-person-details")}
style={{
color:
record.opacity > 0.5 || theme === "dark"
? "var(--theme-white)"
: "var(--theme-black)",
}}
>
<Avatar
src={
record.user.avatar || fallbackAssets.avatar
}
alt={record.user.name || record.user.email}
size={56}
/>
<div className={classes("-person-details__text")}>
<Typography size="lg">
{record.user.name || record.user.email}
</Typography>
<Typography size="s">
{record.percentage.toFixed(2)}%
</Typography>
<Typography size="s">
{new Intl.NumberFormat("en-US", {
style: "currency",
currency: "INR",
}).format(record.amount)}
</Typography>
</div>
</div>
</div>
))}
</div>
</div>
);
};

export default GroupContributions;
1 change: 1 addition & 0 deletions components/Groups/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { default as Contributions } from "./contributions";
export { default as CreateGroup } from "./create";
export { default as GroupHome } from "./home";
export { default as GroupInfo } from "./info";
Expand Down
78 changes: 77 additions & 1 deletion components/Groups/styles.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@
position: sticky;
top: 0;
left: 0;
z-index: 10;

@include theme(dark) {
background-color: #646e8a;
Expand Down Expand Up @@ -373,7 +374,8 @@
}

.group-owed-data,
.group-summary {
.group-summary,
.group-contributions {
width: 100%;
display: flex;
justify-content: flex-start;
Expand All @@ -393,6 +395,7 @@
align-items: flex-start;
flex-direction: column;
gap: 8px;
overflow: hidden;

&-details {
display: flex;
Expand Down Expand Up @@ -462,3 +465,76 @@
object-fit: contain;
}
}

.group-contributions {
width: 100%;
display: flex;
justify-content: flex-start;
align-items: center;
flex-direction: column;
gap: 24px;

&-bar {
--radius: 24px;
width: 100%;
aspect-ratio: 5 / 1;
border-radius: var(--radius);
display: flex;
justify-content: flex-start;
align-items: flex-start;
flex-wrap: nowrap;

@include responsive(phone) {
--radius: 12px;
}

&__item {
height: 100%;
position: relative;

&:first-child {
border-radius: var(--radius) 0 0 var(--radius);
}

&:last-child {
border-radius: 0 var(--radius) var(--radius) 0;
}

&:hover {
cursor: pointer;
box-shadow: var(--shadow-elevation-8dp);
}

&--user {
position: absolute;
bottom: 100%;
left: 50%;
transform: translateX(-50%) translateY(-4px);
opacity: 0;
border-radius: 4px;
background-color: var(--back-shadow);
padding: 4px;
display: flex;
justify-content: flex-start;
align-items: center;
flex-direction: column;
gap: 2px;
text-align: center;
white-space: nowrap;
}

&:hover &--user {
opacity: 1;
}
}
}

&-cards {
width: 100%;
display: flex;
justify-content: flex-start;
align-items: center;
flex-direction: column;
gap: 24px;
}
}
2 changes: 1 addition & 1 deletion components/Groups/summary.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { fallbackAssets } from "@/constants";
import { Avatar, Typography } from "@/library";
import { IBalance } from "@/types";
import { stylesConfig } from "@/utils";
import React from "react";
import styles from "./styles.module.scss";
import { fallbackAssets } from "@/constants";

interface IGroupSummaryProps {
data: Array<IBalance>;
Expand Down
2 changes: 2 additions & 0 deletions connections/api/group.api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
IBalancesSummary,
IExpense,
IGroup,
IShare,
ITransaction,
UpdateGroupData,
} from "@/types";
Expand Down Expand Up @@ -40,6 +41,7 @@ export class GroupApi {
ApiRes<{
expenditure: number;
balances: IBalancesSummary;
shares: Array<IShare>;
}>
> {
const response = await http.get(`/groups/${id}/summary`, { headers });
Expand Down
5 changes: 5 additions & 0 deletions context/slices/ui.slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { createSlice } from "@reduxjs/toolkit";
const initialState: UiSlice = {
vh: 0,
theme: "light",
accentColor: "0, 0, 0",
isSidebarExpanded: true,
networkStatus: "online",
isLoggedIn: false,
Expand Down Expand Up @@ -75,6 +76,9 @@ export const uiSlice = createSlice({
setSideBarLinks: (state, action: Action<Array<Navigation>>) => {
state.sideBarLinks = action.payload;
},
setAccentColor: (state, action: Action<string>) => {
state.accentColor = action.payload;
},
},
});

Expand All @@ -87,6 +91,7 @@ export const {
setIsLoggedIn,
setIsSyncing,
setSideBarLinks,
setAccentColor,
} = uiSlice.actions;

export default uiSlice.reducer;
Expand Down
7 changes: 6 additions & 1 deletion hooks/store.hook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
userSlice,
} from "@/context/slices";
import { AppTheme, IUser } from "@/types";
import { notify } from "@/utils";
import { hexToRgb, notify } from "@/utils";
import { useDispatch, useSelector } from "react-redux";

export const useStore = () => {
Expand All @@ -34,6 +34,11 @@ export const useStore = () => {
dispatch(uiSlice.actions.setTheme("light"));
}
}
const accentColor = getComputedStyle(document.documentElement)
.getPropertyValue("--accent-color-heavy")
.trim();
const accentColorRgb = hexToRgb(accentColor);
dispatch(uiSlice.actions.setAccentColor(accentColorRgb));
};

const syncNetworkStatus = () => {
Expand Down
28 changes: 25 additions & 3 deletions pages/group/[id]/summary.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { authenticatedPage } from "@/client";
import {
Contributions,
GroupMetaData,
GroupPlaceholder,
GroupSummary,
Expand All @@ -13,7 +14,13 @@ import { Seo } from "@/layouts";
import { Typography } from "@/library";
import PageNotFound from "@/pages/404";
import styles from "@/styles/pages/Group.module.scss";
import { IBalancesSummary, IGroup, IUser, ServerSideResult } from "@/types";
import {
IBalancesSummary,
IGroup,
IShare,
IUser,
ServerSideResult,
} from "@/types";
import { getNonEmptyString, notify, stylesConfig } from "@/utils";
import { useRouter } from "next/router";
import React, { useEffect, useState } from "react";
Expand All @@ -25,6 +32,8 @@ type GroupPageProps = {
group: IGroup;
};

type GroupSummaryWindow = "owed" | "summary" | "contributions";

const GroupPage: React.FC<GroupPageProps> = (props) => {
const { setUser, dispatch, groups } = useStore();
const router = useRouter();
Expand All @@ -35,7 +44,8 @@ const GroupPage: React.FC<GroupPageProps> = (props) => {
owes: [],
balances: [],
});
const [activeTab, setActiveTab] = useState<"owed" | "summary">(
const [shares, setShares] = useState<Array<IShare>>([]);
const [activeTab, setActiveTab] = useState<GroupSummaryWindow>(
balances.owes.length > 0 ? "owed" : "summary"
);

Expand All @@ -48,6 +58,7 @@ const GroupPage: React.FC<GroupPageProps> = (props) => {
);
setBalances(fetchedSummary.balances);
setExpenditure(fetchedSummary.expenditure);
setShares(fetchedSummary.shares);
if (fetchedSummary.balances.owes.length > 0) {
setActiveTab("owed");
} else {
Expand Down Expand Up @@ -95,6 +106,15 @@ const GroupPage: React.FC<GroupPageProps> = (props) => {
</Typography>
{balances.owes.length > 0 ? (
<div className={classes("-tabs")}>
<button
className={classes("-tab", {
"-tab--active":
activeTab === "contributions",
})}
onClick={() => setActiveTab("contributions")}
>
<Typography>Contributions</Typography>
</button>
<button
className={classes("-tab", {
"-tab--active": activeTab === "owed",
Expand All @@ -113,7 +133,9 @@ const GroupPage: React.FC<GroupPageProps> = (props) => {
</button>
</div>
) : null}
{activeTab === "owed" ? (
{activeTab === "contributions" ? (
<Contributions shares={shares} />
) : activeTab === "owed" ? (
<OwedRecords
groupId={props.group?.id}
data={balances.owes}
Expand Down
8 changes: 8 additions & 0 deletions types/godown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,11 @@ import { IUser } from "./user";
export type IGodown = {
users: Array<IUser>;
};

export type IShare = {
user: IUser;
amount: number;
percentage: number;
fraction: string;
opacity: number;
};
1 change: 1 addition & 0 deletions types/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export type GroupSlice = Array<IGroup>;
export type UiSlice = {
vh: number;
theme: AppTheme;
accentColor: string;
isSidebarExpanded: boolean;
networkStatus: AppNetworkStatus;
isLoggedIn: boolean;
Expand Down
15 changes: 15 additions & 0 deletions utils/functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -286,3 +286,18 @@ export const simplifyFraction = (fraction: string) => {
}
return fraction;
};

/**
* Converts a hexadecimal color code to RGB.
* @param {string} hex The hexadecimal color code.
* @returns {string} A string in the format "red, green, blue" if the conversion was successful, otherwise null.
*/
export const hexToRgb = (hex: string): string => {
const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
hex = hex.replace(shorthandRegex, (_, r, g, b) => r + r + g + g + b + b);

const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result
? `${parseInt(result[1], 16)}, ${parseInt(result[2], 16)}, ${parseInt(result[3], 16)}`
: hex;
};

0 comments on commit 9f43d47

Please sign in to comment.