Skip to content

Commit a0c8436

Browse files
authored
Merge pull request #26 from gitmotion/feature/add-pwa-registration
Add PWA Registration, Optional CORS Support, docker-compose.yml, toast-manager, and readme.md updates
2 parents 499c987 + 70cbfcd commit a0c8436

File tree

15 files changed

+484
-39
lines changed

15 files changed

+484
-39
lines changed

.gitignore

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,5 +132,11 @@ dist
132132
# Local data files
133133
data/transactions.json
134134

135-
# Development config
136-
nodemon.json
135+
## Development config
136+
# nodemon.json
137+
138+
# Generated PWA Files
139+
/public/*manifest.json
140+
/public/logo.*
141+
/public/assets/logo.*
142+
/public/assets/*manifest.json

README.md

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ A simple, secure personal budgeting app with PIN protection. Track your income a
1818
- 📤 Export to CSV
1919
- 🔍 Filter transactions by type
2020
- 💱 Multi-currency support
21+
- 🌐 PWA Support
2122

2223
## Supported Currencies
2324

@@ -61,6 +62,33 @@ docker run -d \
6162
dumbwareio/dumbbudget:latest
6263
```
6364

65+
```yaml
66+
services:
67+
dumbbudget:
68+
image: dumbwareio/dumbbudget:latest
69+
container_name: dumbbudget
70+
restart: unless-stopped
71+
ports:
72+
- ${DUMBBUDGET_PORT:-3000}:3000
73+
volumes:
74+
- ${DUMBBUDGET_DATA_PATH:-./data}:/app/data
75+
environment:
76+
- DUMBBUDGET_PIN=${DUMBBUDGET_PIN:-} # PIN to access the site
77+
- BASE_URL=${DUMBBUDGET_BASE_URL:-http://localhost:3000} # URL to access the site
78+
- CURRENCY=${DUMBBUDGET_CURRENCY:-USD} # Supported Currency Code: https://github.com/DumbWareio/DumbBudget?tab=readme-ov-file#supported-currencies
79+
- SITE_TITLE=${DUMBBUDGET_SITE_TITLE:-DumbBudget} # Name to show on site
80+
- INSTANCE_NAME=${DUMBBUDGET_INSTANCE_NAME:-} # Name of instance/account
81+
# (OPTIONAL)
82+
# Restrict origins - ex: https://subdomain.domain.tld,https://auth.proxy.tld,http://internalip:port' (default is '*')
83+
# - ALLOWED_ORIGINS=${DUMBBUDGET_ALLOWED_ORIGINS:-http://localhost:3000}
84+
# healthcheck:
85+
# test: wget --spider -q http://127.0.0.1:3000
86+
# start_period: 20s
87+
# interval: 20s
88+
# timeout: 5s
89+
# retries: 3
90+
```
91+
6492
> **Note**: Replace `/path/to/your/data` with the actual path where you want to store your transaction data on the host machine.
6593
6694
### Environment Variables
@@ -93,7 +121,9 @@ PORT=3000
93121
NODE_ENV=development
94122
BASE_URL=http://localhost:3000
95123
CURRENCY=USD
96-
SITE_TITLE='My Account'
124+
SITE_TITLE='DumbBudget'
125+
INSTANCE_NAME='My Account'
126+
ALLOWED_ORIGINS=* # Restrict origins - ex: https://subdomain.domain.tld,https://auth.proxy.tld,http://internalip:port' (default is '*')
97127
```
98128

99129
4. Start the development server:

docker-compose.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
2+
services:
3+
dumbbudget:
4+
image: dumbwareio/dumbbudget:latest
5+
container_name: dumbbudget
6+
restart: unless-stopped
7+
ports:
8+
- ${DUMBBUDGET_PORT:-3000}:3000
9+
volumes:
10+
- ${DUMBBUDGET_DATA_PATH:-./data}:/app/data
11+
environment:
12+
- DUMBBUDGET_PIN=${DUMBBUDGET_PIN:-} # PIN to access the site
13+
- BASE_URL=${DUMBBUDGET_BASE_URL:-http://localhost:3000} # URL to access the site
14+
- CURRENCY=${DUMBBUDGET_CURRENCY:-USD} # Supported Currency Code: https://github.com/DumbWareio/DumbBudget?tab=readme-ov-file#supported-currencies
15+
- SITE_TITLE=${DUMBBUDGET_SITE_TITLE:-DumbBudget} # Name to show on site
16+
- INSTANCE_NAME=${DUMBBUDGET_INSTANCE_NAME:-} # Name of instance/account
17+
# (OPTIONAL)
18+
# Restrict origins - ex: https://subdomain.domain.tld,https://auth.proxy.tld,http://internalip:port' (default is '*')
19+
# - ALLOWED_ORIGINS=${DUMBBUDGET_ALLOWED_ORIGINS:-http://localhost:3000}
20+
# healthcheck:
21+
# test: wget --spider -q http://127.0.0.1:3000
22+
# start_period: 20s
23+
# interval: 20s
24+
# timeout: 5s
25+
# retries: 3

nodemon.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"ignore": ["asset-manifest.json", "manifest.json"]
3+
}

package-lock.json

Lines changed: 25 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
},
1010
"dependencies": {
1111
"cookie-parser": "^1.4.7",
12+
"cors": "^2.8.5",
1213
"dotenv": "^16.3.1",
1314
"dumbdateparser": "^1.2.0",
1415
"express": "^4.18.2",
Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
--success: #4CAF50;
1212
--danger: #f44336;
1313
--card-bg: #ffffff;
14+
--success-status-bg: rgba(37, 99, 235, 0.6);
15+
--danger-status-bg:rgba(220, 38, 38, 0.6);
1416
}
1517

1618
[data-theme="dark"] {
@@ -20,6 +22,8 @@
2022
--border: #404040;
2123
--shadow: 0 2px 4px rgba(0,0,0,0.2);
2224
--card-bg: #363636;
25+
--success-status-bg: rgba(96, 165, 250, 0.5);
26+
--danger-status-bg:rgba(220, 38, 38, 0.5);
2327
}
2428

2529
/* Base styles */
@@ -57,9 +61,9 @@ main {
5761
padding: 1.5rem 1rem 1rem;
5862
border-radius: 8px;
5963
box-shadow: var(--shadow);
60-
width: calc(100% - 1rem);
61-
max-width: 600px;
62-
min-height: calc(100vh - 1rem);
64+
width: 100%;
65+
max-width: 70%;
66+
min-height: calc(100vh - 2rem);
6367
transition: background var(--transition), box-shadow var(--transition);
6468
margin: 0 auto;
6569
display: flex;
@@ -254,14 +258,14 @@ header {
254258
background: var(--card-bg);
255259
border-radius: 8px;
256260
box-shadow: var(--shadow);
257-
width: 75%;
261+
width: 60%;
258262
}
259263

260264
.date-input-group {
261265
display: flex;
262266
align-items: center;
263267
justify-content: center;
264-
gap: 0.5rem;
268+
gap: 0.25rem;
265269
}
266270

267271
.date-input-group input[type="date"] {
@@ -273,7 +277,8 @@ header {
273277
font-size: 0.875rem;
274278
font-family: inherit;
275279
width: auto;
276-
min-width: 130px;
280+
min-width: 45%;
281+
text-align: center;
277282
}
278283

279284
.date-input-group input[type="date"]::-webkit-calendar-picker-indicator {
@@ -292,7 +297,7 @@ header {
292297
font-size: 0.875rem;
293298
}
294299

295-
@media (max-width: 600px) {
300+
@media (max-width: 670px) {
296301
.date-input-group {
297302
flex-direction: column;
298303
gap: 0.25rem;
@@ -642,9 +647,10 @@ footer {
642647
}
643648

644649
/* Responsive adjustments */
645-
@media (max-width: 600px) {
650+
@media (max-width: 860px) {
646651
.container {
647652
padding: 1rem 0.75rem;
653+
max-width: 100%;
648654
}
649655

650656
.summary-cards {
@@ -1008,4 +1014,42 @@ footer {
10081014

10091015
#cancelCategory:hover {
10101016
background: color-mix(in srgb, var(--danger) 85%, black);
1011-
}
1017+
}
1018+
1019+
.toast-container {
1020+
position: fixed;
1021+
bottom: 1rem;
1022+
left: 50%;
1023+
transform: translateX(-50%);
1024+
padding: 0.5rem 1rem;
1025+
display: flex;
1026+
flex-direction: column;
1027+
gap: 10px;
1028+
z-index: 2000;
1029+
}
1030+
1031+
.toast {
1032+
color: #ffffff;
1033+
padding: 0.5rem 1rem;
1034+
border-radius: 20px;
1035+
opacity: 0;
1036+
transition: opacity 0.3s ease-in-out;
1037+
max-width: 300px;
1038+
box-sizing: border-box;
1039+
word-wrap: break-word;
1040+
font-size: 0.875rem;
1041+
cursor: pointer;
1042+
text-align: center;
1043+
}
1044+
1045+
.toast.show {
1046+
opacity: 1;
1047+
}
1048+
1049+
.toast.success {
1050+
background-color: var(--success-status-bg);
1051+
}
1052+
1053+
.toast.error {
1054+
background-color: var(--danger-status-bg);
1055+
}

public/index.html

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,21 @@
55
<meta name="viewport" content="width=device-width, initial-scale=1.0">
66
<title>Loading...</title>
77
<script src="config.js"></script>
8+
<link rel="manifest" href="manifest.json">
89
<script>
10+
// Prevent theme flicker by setting theme immediately
11+
(function() {
12+
const theme = localStorage.getItem('theme') || (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
13+
document.documentElement.setAttribute('data-theme', theme);
14+
})();
915
document.addEventListener('DOMContentLoaded', () => {
10-
const siteTitle = window.appConfig.title || 'DumbBudget';
16+
const siteTitle = window.appConfig.title;
1117
document.title = siteTitle;
1218
document.querySelector('h1').textContent = siteTitle;
1319
});
1420
</script>
1521
<link rel="icon" type="image/svg+xml" href="assets/logo.svg">
16-
<link rel="stylesheet" href="styles.css">
22+
<link rel="stylesheet" href="assets/styles.css">
1723
</head>
1824
<body>
1925
<main>
@@ -120,6 +126,7 @@ <h3>Transactions</h3>
120126
</button>
121127
</footer>
122128
</div>
129+
<div id="toast-container" class="toast-container"></div>
123130
</main>
124131

125132
<!-- Transaction Modal -->
@@ -158,6 +165,6 @@ <h3>Transactions</h3>
158165
</div>
159166
</div>
160167

161-
<script src="script.js"></script>
168+
<script src="script.js" type="module"></script>
162169
</body>
163170
</html>

public/login.html

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,19 @@
66
<title>Loading...</title>
77
<script src="config.js"></script>
88
<script>
9+
// Prevent theme flicker by setting theme immediately
10+
(function() {
11+
const theme = localStorage.getItem('theme') || (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
12+
document.documentElement.setAttribute('data-theme', theme);
13+
})();
914
document.addEventListener('DOMContentLoaded', () => {
10-
const siteTitle = window.appConfig.title || 'DumbBudget';
15+
const siteTitle = window.appConfig.title;
1116
document.title = `${siteTitle} - Login`;
1217
document.querySelector('h1').textContent = siteTitle;
1318
});
1419
</script>
1520
<link rel="icon" type="image/svg+xml" href="assets/logo.svg">
16-
<link rel="stylesheet" href="styles.css">
21+
<link rel="stylesheet" href="assets/styles.css">
1722
</head>
1823
<body>
1924
<main>
@@ -40,6 +45,6 @@ <h2>Enter PIN</h2>
4045
<div class="pin-error" role="alert" aria-hidden="true">Incorrect PIN. Please try again.</div>
4146
</form>
4247
</main>
43-
<script src="script.js"></script>
48+
<script src="script.js" type="module"></script>
4449
</body>
4550
</html>

0 commit comments

Comments
 (0)