mirror of
https://github.com/spliit-app/spliit.git
synced 2026-03-07 12:56:12 +01:00
* I18n with next-intl * package-lock * Finnish translations * Development fix * Use locale for positioning currency symbol * Translations: Expenses.ActiveUserModal * Translations: group 404 * Better translation for ExpenseCard * Apply translations in CategorySelect search * Fix for Finnish translation * Translations for ExpenseDocumentsInput * Translations for CreateFromReceipt * Fix for Finnish translation * Translations for schema errors * Fix for Finnish translation * Fixes for Finnish translations * Prettier --------- Co-authored-by: Sebastien Castiel <sebastien@castiel.me>
96 lines
2.9 KiB
TypeScript
96 lines
2.9 KiB
TypeScript
'use client'
|
|
import { Button } from '@/components/ui/button'
|
|
import { getGroupExpenses } from '@/lib/api'
|
|
import { DateTimeStyle, cn, formatDate } from '@/lib/utils'
|
|
import { Activity, ActivityType, Participant } from '@prisma/client'
|
|
import { ChevronRight } from 'lucide-react'
|
|
import { useLocale, useTranslations } from 'next-intl'
|
|
import Link from 'next/link'
|
|
import { useRouter } from 'next/navigation'
|
|
|
|
type Props = {
|
|
groupId: string
|
|
activity: Activity
|
|
participant?: Participant
|
|
expense?: Awaited<ReturnType<typeof getGroupExpenses>>[number]
|
|
dateStyle: DateTimeStyle
|
|
}
|
|
|
|
function useSummary(activity: Activity, participantName?: string) {
|
|
const t = useTranslations('Activity')
|
|
const participant = participantName ?? t('someone')
|
|
const expense = activity.data ?? ''
|
|
|
|
const tr = (key: string) =>
|
|
t.rich(key, {
|
|
expense,
|
|
participant,
|
|
em: (chunks) => <em>“{chunks}”</em>,
|
|
strong: (chunks) => <strong>{chunks}</strong>,
|
|
})
|
|
|
|
if (activity.activityType == ActivityType.UPDATE_GROUP) {
|
|
return <>{tr('settingsModified')}</>
|
|
} else if (activity.activityType == ActivityType.CREATE_EXPENSE) {
|
|
return <>{tr('expenseCreated')}</>
|
|
} else if (activity.activityType == ActivityType.UPDATE_EXPENSE) {
|
|
return <>{tr('expenseUpdated')}</>
|
|
} else if (activity.activityType == ActivityType.DELETE_EXPENSE) {
|
|
return <>{tr('expenseDeleted')}</>
|
|
}
|
|
}
|
|
|
|
export function ActivityItem({
|
|
groupId,
|
|
activity,
|
|
participant,
|
|
expense,
|
|
dateStyle,
|
|
}: Props) {
|
|
const router = useRouter()
|
|
const locale = useLocale()
|
|
|
|
const expenseExists = expense !== undefined
|
|
const summary = useSummary(activity, participant?.name)
|
|
|
|
return (
|
|
<div
|
|
className={cn(
|
|
'flex justify-between sm:rounded-lg px-2 sm:pr-1 sm:pl-2 py-2 text-sm hover:bg-accent gap-1 items-stretch',
|
|
expenseExists && 'cursor-pointer',
|
|
)}
|
|
onClick={() => {
|
|
if (expenseExists) {
|
|
router.push(`/groups/${groupId}/expenses/${activity.expenseId}/edit`)
|
|
}
|
|
}}
|
|
>
|
|
<div className="flex flex-col justify-between items-start">
|
|
{dateStyle !== undefined && (
|
|
<div className="mt-1 text-xs/5 text-muted-foreground">
|
|
{formatDate(activity.time, locale, { dateStyle })}
|
|
</div>
|
|
)}
|
|
<div className="my-1 text-xs/5 text-muted-foreground">
|
|
{formatDate(activity.time, locale, { timeStyle: 'short' })}
|
|
</div>
|
|
</div>
|
|
<div className="flex-1">
|
|
<div className="m-1">{summary}</div>
|
|
</div>
|
|
{expenseExists && (
|
|
<Button
|
|
size="icon"
|
|
variant="link"
|
|
className="self-center hidden sm:flex w-5 h-5"
|
|
asChild
|
|
>
|
|
<Link href={`/groups/${groupId}/expenses/${activity.expenseId}/edit`}>
|
|
<ChevronRight className="w-4 h-4" />
|
|
</Link>
|
|
</Button>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|