Skip to content

Commit

Permalink
export functionality added for friends section (#123)
Browse files Browse the repository at this point in the history
* export functionality added

* added export button next to add expence
  • Loading branch information
KIWILmao authored Oct 14, 2024
1 parent cb5ac73 commit 3a19b2b
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 0 deletions.
120 changes: 120 additions & 0 deletions src/components/Friend/Export.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import React from 'react';
import { Button } from '~/components/ui/button';
import { format } from 'date-fns';
import { SplitType } from '@prisma/client';
import { Download } from 'lucide-react';
import { toUIString } from '~/utils/numbers';

interface ExpenseParticipant {
expenseId: string;
userId: number;
amount: number;
}

interface Expense {
id: string;
paidBy: number;
addedBy: number;
name: string;
category: string;
amount: number;
splitType: SplitType;
expenseDate: Date;
createdAt: Date;
updatedAt: Date;
currency: string;
fileKey: string | null;
groupId: number | null;
deletedAt: Date | null;
deletedBy: number | null;
expenseParticipants: ExpenseParticipant[];
}

interface ExportCSVProps {
expenses: Expense[];
fileName: string;
currentUserId: number;
friendName: string;
friendId: string | number;
disabled?: boolean;
}

export const Export: React.FC<ExportCSVProps> = ({
expenses,
fileName,
currentUserId,
friendName,
friendId,
disabled = false,
}) => {
const headers = [
'Paid By',
'Name',
'Category',
'Amount',
'Split Type',
'Expense Date',
'Currency',
'You Lent',
'You Owe',
'Settlement',
];

const exportToCSV = () => {
const csvHeaders = headers.join(',');
const csvData = expenses.map((expense) => {
const youPaid = expense.paidBy === currentUserId;
const yourExpense = expense.expenseParticipants.find(
(p) => p.userId === (youPaid ? friendId : currentUserId),
);

const isSettlement = expense.splitType === SplitType.SETTLEMENT;

return [
expense.paidBy === currentUserId ? 'You' : friendName,
expense.name,
expense.category,
toUIString(expense?.amount ?? 0),
expense.splitType,
format(new Date(expense.expenseDate), 'yyyy-MM-dd HH:mm:ss'),
expense.currency,
youPaid && !isSettlement ? toUIString(yourExpense?.amount ?? 0) : 0,
!youPaid && !isSettlement ? toUIString(yourExpense?.amount ?? 0) : 0,
isSettlement ? toUIString(yourExpense?.amount ?? 0) : 0,
];
});

const csvContent = [
csvHeaders,
...csvData.map((row) =>
row
.map((cell) => (typeof cell === 'string' && cell.includes(',') ? `"${cell}"` : cell))
.join(','),
),
].join('\n');

const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
const link = document.createElement('a');
if (link.download !== undefined) {
const url = URL.createObjectURL(blob);
link.setAttribute('href', url);
link.setAttribute('download', `${fileName}.csv`);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
};

return (
<Button
size="sm"
variant="secondary"
className="w-[150px] gap-1 text-sm lg:w-[180px]"
onClick={exportToCSV}
disabled={disabled}
>
<Download className="h-4 w-4 text-white" size={20} /> Export
</Button>
);
};
9 changes: 9 additions & 0 deletions src/pages/balances/[friendId].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { useRouter } from 'next/router';
import { type NextPageWithUser } from '~/types';
import { motion } from 'framer-motion';
import { DeleteFriend } from '~/components/Friend/DeleteFriend';
import { Export } from '~/components/Friend/Export';

const FriendPage: NextPageWithUser = ({ user }) => {
const router = useRouter();
Expand Down Expand Up @@ -138,6 +139,14 @@ const FriendPage: NextPageWithUser = ({ user }) => {
<PlusIcon className="h-4 w-4 text-gray-400" /> Add Expense
</Button>
</Link>
<Export
expenses={expenses.data ?? []}
fileName={`expenses_with_${friendQuery.data?.name}`}
currentUserId={user.id}
friendName={friendQuery.data?.name ?? ''}
friendId={friendQuery.data?.id ?? ''}
disabled={!expenses.data || expenses.data.length === 0}
/>
{/* <Button size="sm" className="gap-1 text-sm lg:w-[180px]" variant="secondary">
<Bell className="h-4 w-4 text-gray-400" />
Remind
Expand Down

0 comments on commit 3a19b2b

Please sign in to comment.