Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/build-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ on:
branches:
- main
- copilot/**
- clean-build

jobs:
build-windows:
Expand Down
6 changes: 6 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"cSpell.words": [
"Anik",
"Chowdhury"
]
}
144 changes: 138 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,151 @@
# Data Entry App
# Data Entry App# Data Entry App

An offline data entry and data collection application for managing data efficiently.

## Features

- Offline data entry
- Data collection
- Data management
A customizable offline data entry application for managing church records and other data efficiently.An offline data entry and data collection application for managing data efficiently.



## Features## Features



### Core Features- Offline data entry

- **Offline Data Entry**: All data persists locally using SQL.js- Data collection

- **Full CRUD Operations**: Create, Read, Update, Delete records- Data management
Comment on lines +1 to +17

Copilot AI Nov 6, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The README.md file contains duplicated content. Lines 1-17 repeat the headers "Data Entry App", "Features", and feature items, causing formatting issues. The duplicate text should be removed to clean up the documentation.

Copilot uses AI. Check for mistakes.

- **Excel Export**: Export records to Excel with church record template compatibility

- **Search & Filter**: Real-time search across all fields## Installation



### Customization Features ✨```bash

- **Editable App Title**: Click the header to rename your applicationnpm install

- **Dynamic Field Management**: ```

- Add custom fields with different types (text, textarea, number, date, email)

- Delete fields you don't need## Author

- Update field properties (label, placeholder, required status)

- Reorder fields (drag handles)Anik Chowdhury

- **Persistent Configuration**: All customizations saved in browser localStorage

- **Reset to Default**: Restore the original 15 church record fields anytime## License



### Default Church Record FieldsISC

1. Name of Church
2. Place
3. Husband Name
4. Wife Name
5. Father Name
6. Mother Name
7. Relation
8. Name
9. Birth
10. BAPT (Baptism)
11. CONF (Confirmation)
12. 1 COM (First Communion)
13. Marriage
14. Death
15. Note

## Installation

```bash
npm install
```

## Usage

### Run the Application
```bash
npm start
```

### Build Windows Installer
```bash
npm run build:win
```
The installer will be created in the `release3/` directory.

### Customize Your App

1. **Change the App Title**:
- Click on the header text "Church Records Data Entry"
- Type your custom name
- Press Enter to save

2. **Manage Fields**:
- Click the "⚙️ Customize Fields" button
- **Add Field**: Click "+ Add New Field"
- **Edit Field**: Modify label, ID, type, placeholder, or required status
- **Delete Field**: Click the red "Delete" button
- Click "Save Changes" to apply

3. **Reset to Default**:
- Open field settings
- Click "Reset to Default"
- Confirm to restore original 15 church fields

## Technology Stack

- **Electron** v25.3.0 - Desktop application framework
- **sql.js** v1.9.0 - SQLite database (WASM, no native dependencies)
- **xlsx** v0.18.5 - Excel file generation
- **electron-builder** v24.13.3 - Installer packaging

## Data Storage

- **Database**: `data.db` (SQLite via sql.js)
- **Excel Exports**: `records.xlsx`
- **Customizations**: Browser localStorage
- `customFields` - Field configuration
- `appTitle` - Application title

## Development

### Project Structure
```
data-entry-app/
├── main.js # Electron main process
├── preload.js # Secure IPC bridge
├── database.js # Database operations
├── index.html # Main UI structure
├── renderer.js # UI logic
├── field-manager.js # Dynamic field management
├── style.css # Dark theme styling
├── package.json # Dependencies and build config
└── .github/
└── workflows/
└── build-windows.yml # CI/CD workflow
```

### Security
- Context isolation enabled
- Sandbox mode enabled
- No node integration in renderer
- Secure IPC via contextBridge

## CI/CD

GitHub Actions workflow automatically builds Windows installer on push to:
- `main` branch
- `clean-build` branch
- Any `copilot/*` branches

Download built installer from GitHub Actions artifacts.

## Author

Anik Chowdhury
Expand Down
41 changes: 0 additions & 41 deletions create-repo.js

This file was deleted.

69 changes: 60 additions & 9 deletions database.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,24 @@ class Database {
this.db = new SQL.Database(fileBuffer);
} else {
this.db = new SQL.Database();
this.db.run('CREATE TABLE records (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, email TEXT, age INTEGER)');
this.db.run(`CREATE TABLE records (
id INTEGER PRIMARY KEY AUTOINCREMENT,
church_name TEXT,
place TEXT,
husband_name TEXT,
wife_name TEXT,
father_name TEXT,
mother_name TEXT,
relation TEXT,
name TEXT,
birth TEXT,
bapt TEXT,
conf TEXT,
first_com TEXT,
marriage TEXT,
death TEXT,
note TEXT
)`);
this._persist();
}
}
Expand All @@ -36,10 +53,18 @@ class Database {
fs.writeFileSync(DB_FILE, buffer);
}

async insertData({ name, email, age }) {
async insertData(record) {
await this.ready;
const stmt = this.db.prepare('INSERT INTO records (name, email, age) VALUES (?, ?, ?)');
stmt.run([name, email, parseInt(age, 10) || null]);
const stmt = this.db.prepare(`INSERT INTO records (
church_name, place, husband_name, wife_name, father_name, mother_name,
relation, name, birth, bapt, conf, first_com, marriage, death, note
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
stmt.run([
record.church_name, record.place, record.husband_name, record.wife_name,
record.father_name, record.mother_name, record.relation, record.name,
record.birth, record.bapt, record.conf, record.first_com,
record.marriage, record.death, record.note
]);
stmt.free();
this._persist();
return true;
Expand All @@ -54,10 +79,18 @@ class Database {
return rows;
}

async updateData({ id, name, email, age }) {
async updateData(record) {
await this.ready;
const stmt = this.db.prepare('UPDATE records SET name=?, email=?, age=? WHERE id=?');
stmt.run([name, email, parseInt(age, 10) || null, parseInt(id, 10)]);
const stmt = this.db.prepare(`UPDATE records SET
church_name=?, place=?, husband_name=?, wife_name=?, father_name=?, mother_name=?,
relation=?, name=?, birth=?, bapt=?, conf=?, first_com=?, marriage=?, death=?, note=?
WHERE id=?`);
stmt.run([
record.church_name, record.place, record.husband_name, record.wife_name,
record.father_name, record.mother_name, record.relation, record.name,
record.birth, record.bapt, record.conf, record.first_com,
record.marriage, record.death, record.note, parseInt(record.id, 10)
]);
stmt.free();
this._persist();
return true;
Expand All @@ -74,9 +107,27 @@ class Database {

async exportToExcel() {
const rows = await this.getAllData();
const worksheet = xlsx.utils.json_to_sheet(rows);
// Map to template column names
const exportData = rows.map(r => ({
'Name of Church': r.church_name,
'Place': r.place,
'Husband Name': r.husband_name,
'Wife Name': r.wife_name,
'Father Name': r.father_name,
'Mother Name': r.mother_name,
'Relation': r.relation,
'Name': r.name,
'Birth': r.birth,
'BAPT': r.bapt,
'CONF': r.conf,
'1 COM': r.first_com,
'Marriage': r.marriage,
'Death': r.death,
'Note': r.note
}));
const worksheet = xlsx.utils.json_to_sheet(exportData);
const workbook = xlsx.utils.book_new();
xlsx.utils.book_append_sheet(workbook, worksheet, 'Data');
xlsx.utils.book_append_sheet(workbook, worksheet, 'Church Records');
xlsx.writeFile(workbook, 'records.xlsx');
return 'records.xlsx';
}
Expand Down
Loading