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
62 changes: 39 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,30 +1,46 @@
# Instant Calc 🧮

Instant Calc is a custom project, providing a simple and intuitive way to perform calculations and evaluate expressions in your web browser.
Real-time calculation notebook with syntax highlighting, deduction tracking, and cloud sync.

## Features ✏️
## Features

- Natural Language Syntax: Perform calculations using familiar phrases and expressions.
- Real-Time Evaluation: Instantly see the results of your calculations as you type.
- Variable Assignment: Define and use variables to store values for repeated use.
- Expression Parsing: Evaluate complex expressions with operators, functions, and parentheses.
- Commenting: Add comments to your calculations for better organization and understanding.
- Responsive Design: Enjoy a seamless experience across different devices and screen sizes.
- **Syntax Highlighting** — headings, comments, expenses, and variables colour-coded as you type
- **Real-Time Evaluation** — results appear instantly in the output panel; no submit button needed
- **Variable Assignment** — `name = expression` or `name: expression` stores a value
- **Auto-Commenting** — set a deduction day per expense; past-due lines are commented out automatically
- **Due Next mode** — toggle to preview next month's deductions
- **Rich Text Input** — powered by Quill, with coloured formatting preserved
- **Cloud Sync** — sign in with Google to save notebooks to Firebase
- **Dark Mode** — toggle between light and dark themes
- **PWA** — installable as a progressive web app

## Usage

1. Type your calculations in the input textarea.
2. Press Enter or click outside the textarea to evaluate the expression.
3. The output will be displayed in the output textarea.
4. Store operations in a variable by starting with `name=`
5. Add comments using the `//` prefix to document your calculations.
6. Add headings using the `#` prefix for ease of labelling.
7. Make use of reserved keywords ["prev", "sum", "to", "monthlyPayDate", "in"]

## Technologies Used

- React.js
- Next.js
- CSS Modules
- TypeScript
- Firebase
1. Type into the left panel (rich-text editor).
2. Each line is evaluated on the fly — output appears on the right.
3. `name: value` or `name = value` creates a variable you can reuse later.
4. `//` comments out a line, `#` creates a heading.
5. Keywords: `prev` (last result), `sum` (running total), `monthlyPayDate` (days until payday).
6. Click the calendar icon 🌿 next to an expense to set its deduction day.
7. Sign in to save automatically.

## Quick Start

```bash
npm install
npm run dev # local dev server
npm test # vitest
npm run build # production build
npm run lint # eslint + prettier
```

## Tech Stack

- **Framework:** Next.js 14 (Pages Router), React 18
- **Language:** TypeScript
- **Editor:** react-quill (Quill rich text editor)
- **Styling:** Tailwind CSS + CSS Modules
- **State:** React hooks (useState, useCallback, useEffect)
- **Database:** Firebase Realtime Database (auth + data sync)
- **Animation:** Framer Motion
- **Testing:** Vitest
37 changes: 37 additions & 0 deletions helpers/__tests__/calculations.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,18 @@ describe("parseVariableLine", () => {
isCommented: false,
});
});

it("returns null for empty string", () => {
expect(parseVariableLine("")).toBeNull();
});

it("returns null for whitespace-only line", () => {
expect(parseVariableLine(" ")).toBeNull();
});

it("returns null for tab-only line", () => {
expect(parseVariableLine("\t")).toBeNull();
});
});

describe("getAutoCommentedLines", () => {
Expand Down Expand Up @@ -174,6 +186,31 @@ describe("getAutoCommentedLines", () => {
);
expect(result).toEqual(["rent=1000"]);
});

it("preserves blank lines through auto-commenting", () => {
const result = getAutoCommentedLines(
["rent: 1000", "", "food: 250"],
{},
false,
10,
);
expect(result).toEqual(["rent: 1000", "", "food: 250"]);
});

it("handles blank lines between commented and active lines", () => {
const result = getAutoCommentedLines(
["//rent: 1000", "", "food: 250"],
{ rent: 15 },
false,
20,
);
expect(result).toEqual(["//rent: 1000", "", "food: 250"]);
});

it("handles trailing blank line", () => {
const result = getAutoCommentedLines(["rent: 1000", ""], {}, false, 10);
expect(result).toEqual(["rent: 1000", ""]);
});
});

describe("tryGetValue", () => {
Expand Down
1 change: 0 additions & 1 deletion helpers/getCurrencyConversion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { acceptedCurrencySymbols } from "../currencies";
export const isCurrency = async (name: string) => {
let withToCode: string | boolean = false;
const hasIn = name.includes("in");
console.log(hasIn);
if (hasIn) {
const expression = name
.split("in")
Expand Down
Loading
Loading