mirror of
https://github.com/spliit-app/spliit.git
synced 2026-02-18 21:46:13 +01:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1cd2b273f9 | ||
|
|
1ad470309b |
42
.devcontainer/devcontainer.json
Normal file
42
.devcontainer/devcontainer.json
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
|
||||||
|
// README at: https://github.com/devcontainers/templates/tree/main/src/javascript-node-postgres
|
||||||
|
{
|
||||||
|
"name": "spliit",
|
||||||
|
"dockerComposeFile": "docker-compose.yml",
|
||||||
|
"service": "app",
|
||||||
|
|
||||||
|
// Features to add to the dev container. More info: https://containers.dev/features.
|
||||||
|
// "features": {
|
||||||
|
// "ghcr.io/frntn/devcontainers-features/prism:1": {}
|
||||||
|
// },
|
||||||
|
|
||||||
|
// Use 'postCreateCommand' to run commands after the container is created.
|
||||||
|
"postCreateCommand": "cp container.env.example .env && npm install",
|
||||||
|
"postAttachCommand": {
|
||||||
|
"npm": "npm run dev"
|
||||||
|
},
|
||||||
|
|
||||||
|
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||||
|
// This can be used to network with other containers or with the host.
|
||||||
|
"forwardPorts": [3000, 5432],
|
||||||
|
"portsAttributes": {
|
||||||
|
"3000": {
|
||||||
|
"label": "App"
|
||||||
|
},
|
||||||
|
"5432": {
|
||||||
|
"label": "PostgreSQL"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Configure tool-specific properties.
|
||||||
|
"customizations": {
|
||||||
|
"codespaces": {
|
||||||
|
"openFiles": [
|
||||||
|
"README.md"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
|
||||||
|
// "remoteUser": "root"
|
||||||
|
}
|
||||||
33
.devcontainer/docker-compose.yml
Normal file
33
.devcontainer/docker-compose.yml
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
app:
|
||||||
|
image: mcr.microsoft.com/devcontainers/typescript-node:latest
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- ../..:/workspaces:cached
|
||||||
|
|
||||||
|
# Overrides default command so things don't shut down after the process ends.
|
||||||
|
command: sleep infinity
|
||||||
|
|
||||||
|
# Runs app on the same network as the database container, allows "forwardPorts" in devcontainer.json function.
|
||||||
|
network_mode: service:db
|
||||||
|
|
||||||
|
# Use "forwardPorts" in **devcontainer.json** to forward an app port locally.
|
||||||
|
# (Adding the "ports" property to this file will not forward from a Codespace.)
|
||||||
|
|
||||||
|
db:
|
||||||
|
image: postgres:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- postgres-data:/var/lib/postgresql/data
|
||||||
|
environment:
|
||||||
|
POSTGRES_PASSWORD: 1234
|
||||||
|
POSTGRES_USER: postgres
|
||||||
|
POSTGRES_DB: postgres
|
||||||
|
|
||||||
|
# Add "forwardPorts": ["5432"] to **devcontainer.json** to forward PostgreSQL locally.
|
||||||
|
# (Adding the "ports" property to this file will not forward from a Codespace.)
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
postgres-data:
|
||||||
@@ -23,6 +23,12 @@ const nextConfig = {
|
|||||||
images: {
|
images: {
|
||||||
remotePatterns
|
remotePatterns
|
||||||
},
|
},
|
||||||
|
// Required to run in a codespace (see https://github.com/vercel/next.js/issues/58019)
|
||||||
|
experimental: {
|
||||||
|
serverActions: {
|
||||||
|
allowedOrigins: ['localhost:3000'],
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = nextConfig
|
module.exports = nextConfig
|
||||||
|
|||||||
43
src/app/groups/[groupId]/expenses/active-user-balance.tsx
Normal file
43
src/app/groups/[groupId]/expenses/active-user-balance.tsx
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
'use client'
|
||||||
|
import { Money } from '@/components/money'
|
||||||
|
import { getBalances } from '@/lib/balances'
|
||||||
|
import { useActiveUser } from '@/lib/hooks'
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
groupId: string
|
||||||
|
currency: string
|
||||||
|
expense: Parameters<typeof getBalances>[0][number]
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ActiveUserBalance({ groupId, currency, expense }: Props) {
|
||||||
|
const activeUserId = useActiveUser(groupId)
|
||||||
|
if (activeUserId === null || activeUserId === '' || activeUserId === 'None') {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const balances = getBalances([expense])
|
||||||
|
let fmtBalance = <>You are not involved</>
|
||||||
|
if (Object.hasOwn(balances, activeUserId)) {
|
||||||
|
const balance = balances[activeUserId]
|
||||||
|
let balanceDetail = <></>
|
||||||
|
if (balance.paid > 0 && balance.paidFor > 0) {
|
||||||
|
balanceDetail = (
|
||||||
|
<>
|
||||||
|
{' ('}
|
||||||
|
<Money {...{ currency, amount: balance.paid }} />
|
||||||
|
{' - '}
|
||||||
|
<Money {...{ currency, amount: balance.paidFor }} />
|
||||||
|
{')'}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
fmtBalance = (
|
||||||
|
<>
|
||||||
|
Your balance:{' '}
|
||||||
|
<Money {...{ currency, amount: balance.total }} bold colored />
|
||||||
|
{balanceDetail}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return <div className="text-xs text-muted-foreground">{fmtBalance}</div>
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
import { ActiveUserBalance } from '@/app/groups/[groupId]/expenses/active-user-balance'
|
||||||
import { CategoryIcon } from '@/app/groups/[groupId]/expenses/category-icon'
|
import { CategoryIcon } from '@/app/groups/[groupId]/expenses/category-icon'
|
||||||
import { Button } from '@/components/ui/button'
|
import { Button } from '@/components/ui/button'
|
||||||
import { SearchBar } from '@/components/ui/search-bar'
|
import { SearchBar } from '@/components/ui/search-bar'
|
||||||
@@ -151,6 +152,9 @@ export function ExpenseList({
|
|||||||
</Fragment>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
<div className="text-xs text-muted-foreground">
|
||||||
|
<ActiveUserBalance {...{ groupId, currency, expense }} />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col justify-between items-end">
|
<div className="flex flex-col justify-between items-end">
|
||||||
<div
|
<div
|
||||||
|
|||||||
31
src/components/money.tsx
Normal file
31
src/components/money.tsx
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
'use client'
|
||||||
|
import { cn, formatCurrency } from '@/lib/utils'
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
currency: string
|
||||||
|
amount: number
|
||||||
|
bold?: boolean
|
||||||
|
colored?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Money({
|
||||||
|
currency,
|
||||||
|
amount,
|
||||||
|
bold = false,
|
||||||
|
colored = false,
|
||||||
|
}: Props) {
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
className={cn(
|
||||||
|
colored && amount <= 1
|
||||||
|
? 'text-red-600'
|
||||||
|
: colored && amount >= 1
|
||||||
|
? 'text-green-600'
|
||||||
|
: '',
|
||||||
|
bold && 'font-bold',
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{formatCurrency(currency, amount)}
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user