diff --git a/.github/coderabbit.yml b/.github/coderabbit.yml
new file mode 100644
index 0000000..46ae701
--- /dev/null
+++ b/.github/coderabbit.yml
@@ -0,0 +1,212 @@
+# CodeRabbit Configuration for NickSpace Playground
+# https://docs.coderabbit.ai/configuration-file
+
+# Language settings
+language: en-US
+
+# Review settings
+reviews:
+ # Enable/disable auto reviews
+ auto_review: true
+
+ # Draft PR reviews
+ draft_as_pending: true
+
+ # Review scope
+ review:
+ # Files to review
+ include:
+ - "**/*.js"
+ - "**/*.jsx"
+ - "**/*.ts"
+ - "**/*.tsx"
+ - "**/*.css"
+ - "**/*.scss"
+ - "**/*.json"
+ - "**/*.md"
+ - "**/*.yml"
+ - "**/*.yaml"
+
+ # Files to exclude from review
+ exclude:
+ - "node_modules/**"
+ - "build/**"
+ - "dist/**"
+ - "coverage/**"
+ - "*.min.js"
+ - "*.bundle.js"
+ - "package-lock.json"
+ - "yarn.lock"
+
+ # Auto-approve changes to these files
+ auto_approve:
+ - "README.md" # documentation updates
+ - "CHANGELOG.md"
+
+ # Require manual approval for these critical files
+ require_manual_approval:
+ - "src/App.js"
+ - ".github/**"
+ - "public/index.html"
+ - "CLAUDE.md"
+
+# Code quality rules
+rules:
+ # JavaScript/React specific rules
+ javascript:
+ # Performance
+ - check_unused_variables: true
+ - check_console_logs: warn
+ - check_debugger_statements: error
+ - suggest_const_over_let: true
+
+ # React specific
+ - check_react_hooks_dependencies: true
+ - suggest_react_memo: true
+ - check_jsx_key_props: true
+ - suggest_functional_components: true
+
+ # General code quality
+ - max_function_length: 50
+ - max_file_length: 500
+ - suggest_early_returns: true
+ - check_duplicate_code: true
+
+ # CSS specific rules
+ css:
+ - check_unused_styles: true
+ - suggest_css_variables: true
+ - check_responsive_units: true
+ - prefer_flexbox_grid: true
+
+ # Security rules
+ security:
+ - check_hardcoded_secrets: error
+ - check_vulnerable_dependencies: warn
+ - check_unsafe_html: error
+
+# Comment settings
+comments:
+ # Comment behavior
+ tone: friendly
+ max_comments_per_review: 15
+
+ # Focus areas for comments
+ focus_areas:
+ - performance
+ - security
+ - maintainability
+ - accessibility
+ - best_practices
+ - code_style
+
+ # Specific comment types
+ suggest:
+ - performance_improvements: true
+ - accessibility_improvements: true
+ - code_simplification: true
+ - better_naming: true
+ - error_handling: true
+
+ # Don't comment on these (auto-fix instead)
+ auto_fix:
+ - formatting
+ - simple_typos
+ - missing_semicolons
+ - trailing_whitespace
+
+# Project-specific settings
+project:
+ # Framework detection
+ framework: react
+
+ # Build tools
+ build_tools:
+ - npm
+ - create-react-app
+
+ # Testing framework
+ testing_framework: jest
+
+ # Deployment
+ deployment_platform: github_pages
+
+# Integration settings
+integrations:
+ # GitHub settings
+ github:
+ # PR title suggestions
+ suggest_pr_titles: true
+
+ # Auto-assign reviewers based on file changes
+ auto_assign_reviewers:
+ - "src/components/GameTheory/**": ["@game-theory-expert"]
+ - "src/components/Pathfinding/**": ["@algorithms-expert"]
+ - "src/components/IncomeTax/**": ["@finance-expert"]
+ - "**/*.css": ["@ui-ux-expert"]
+
+ # PR labels
+ auto_labels:
+ - path: "src/components/**/*.js"
+ labels: ["frontend", "react"]
+ - path: "**/*.css"
+ labels: ["styling", "ui"]
+ - path: "**/*.md"
+ labels: ["documentation"]
+ - path: ".github/**"
+ labels: ["ci/cd", "config"]
+ - path: "src/components/IncomeTax/**"
+ labels: ["feature", "calculator"]
+
+# Custom rules for this project
+custom_rules:
+ # Educational project specific rules
+ - name: "educational_clarity"
+ description: "Ensure code is educational and well-documented"
+ pattern: "src/components/**/*.js"
+ checks:
+ - has_component_description: warn
+ - has_prop_types: suggest
+ - has_usage_examples: suggest
+
+ # Calculator specific rules
+ - name: "calculator_accuracy"
+ description: "Ensure calculator components have proper validation"
+ pattern: "src/components/*Calculator/**/*.js"
+ checks:
+ - has_input_validation: error
+ - has_error_handling: error
+ - has_boundary_testing: warn
+
+ # Performance rules for interactive components
+ - name: "interactive_performance"
+ description: "Ensure interactive components are optimized"
+ pattern: "src/components/**/*.js"
+ checks:
+ - uses_react_memo_when_needed: suggest
+ - uses_callback_for_handlers: suggest
+ - minimal_re_renders: warn
+
+# Notification settings
+notifications:
+ # When to notify
+ events:
+ - review_completed
+ - high_priority_issues
+ - security_vulnerabilities
+
+ # Notification channels (customize based on your setup)
+ channels:
+ - github_comments
+ - github_reviews
+
+# Learning and improvement
+learning:
+ # Track improvement over time
+ track_metrics: true
+
+ # Suggest learning resources
+ suggest_resources: true
+
+ # Focus on educational value since this is a playground project
+ educational_mode: true
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 775d6f3..63f4f63 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -16604,17 +16604,16 @@
}
},
"node_modules/typescript": {
- "version": "5.8.3",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
- "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
- "license": "Apache-2.0",
+ "version": "4.9.5",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
+ "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
"peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
- "node": ">=14.17"
+ "node": ">=4.2.0"
}
},
"node_modules/unbox-primitive": {
diff --git a/src/App.js b/src/App.js
index d0b0a6a..3418b47 100644
--- a/src/App.js
+++ b/src/App.js
@@ -4,6 +4,7 @@ import Home from "./Home";
import Pathfinding from "./Pathfinding";
import GameTheory from "./components/GameTheory/GameTheory";
import ProjectCalculator from "./ProjectCalculator";
+import IncomeTaxCalculator from "./components/IncomeTax/IncomeTaxCalculator";
import Algo from './components/AlgoAndDs/AlgoAndDs';
import './App.css';
@@ -15,6 +16,7 @@ function App() {
} />
} />
} />
+ } />
} />
diff --git a/src/components/IncomeTax/IncomeTaxCalculator.css b/src/components/IncomeTax/IncomeTaxCalculator.css
new file mode 100644
index 0000000..2af834c
--- /dev/null
+++ b/src/components/IncomeTax/IncomeTaxCalculator.css
@@ -0,0 +1,376 @@
+.income-tax-container {
+ max-width: 1400px;
+ margin: 0 auto;
+ padding: 2rem;
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ min-height: 100vh;
+}
+
+.tax-header {
+ text-align: center;
+ margin-bottom: 3rem;
+ color: white;
+}
+
+.tax-header h1 {
+ font-size: 2.5rem;
+ margin-bottom: 0.5rem;
+ text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
+}
+
+.tax-header p {
+ font-size: 1.1rem;
+ opacity: 0.9;
+ margin: 0;
+}
+
+.tax-content {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 2rem;
+ align-items: start;
+}
+
+@media (max-width: 1024px) {
+ .tax-content {
+ grid-template-columns: 1fr;
+ }
+}
+
+.tax-input-section {
+ display: flex;
+ flex-direction: column;
+ gap: 1.5rem;
+}
+
+.input-card {
+ background: white;
+ border-radius: 12px;
+ padding: 2rem;
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
+ backdrop-filter: blur(10px);
+ border: 1px solid rgba(255, 255, 255, 0.2);
+}
+
+.input-card h2 {
+ color: #333;
+ margin-bottom: 1.5rem;
+ font-size: 1.4rem;
+ border-bottom: 2px solid #667eea;
+ padding-bottom: 0.5rem;
+}
+
+.input-group {
+ margin-bottom: 1rem;
+}
+
+.input-group label {
+ display: block;
+ margin-bottom: 0.5rem;
+ font-weight: 600;
+ color: #555;
+ font-size: 0.9rem;
+}
+
+.input-group input {
+ width: 100%;
+ padding: 0.75rem;
+ border: 2px solid #e1e5e9;
+ border-radius: 8px;
+ font-size: 1rem;
+ transition: all 0.3s ease;
+ background: #f8f9fa;
+}
+
+.input-group input:focus {
+ outline: none;
+ border-color: #667eea;
+ background: white;
+ box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
+}
+
+.income-input {
+ font-size: 1.2rem !important;
+ font-weight: 600;
+ padding: 1rem !important;
+ background: linear-gradient(45deg, #f8f9fa, #e9ecef) !important;
+}
+
+.relief-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
+ gap: 1rem;
+}
+
+.button-group {
+ display: flex;
+ gap: 1rem;
+ justify-content: center;
+}
+
+.calculate-btn, .reset-btn {
+ padding: 1rem 2rem;
+ border: none;
+ border-radius: 8px;
+ font-size: 1rem;
+ font-weight: 600;
+ cursor: pointer;
+ transition: all 0.3s ease;
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+}
+
+.calculate-btn {
+ background: linear-gradient(45deg, #667eea, #764ba2);
+ color: white;
+ box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3);
+}
+
+.calculate-btn:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4);
+}
+
+.reset-btn {
+ background: linear-gradient(45deg, #6c757d, #495057);
+ color: white;
+ box-shadow: 0 4px 15px rgba(108, 117, 125, 0.3);
+}
+
+.reset-btn:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 6px 20px rgba(108, 117, 125, 0.4);
+}
+
+.tax-results-section {
+ display: flex;
+ flex-direction: column;
+ gap: 1.5rem;
+}
+
+.results-card {
+ background: white;
+ border-radius: 12px;
+ padding: 2rem;
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
+ border: 1px solid rgba(255, 255, 255, 0.2);
+}
+
+.results-card h2 {
+ color: #333;
+ margin-bottom: 1.5rem;
+ font-size: 1.4rem;
+ border-bottom: 2px solid #28a745;
+ padding-bottom: 0.5rem;
+}
+
+.results-summary {
+ display: flex;
+ flex-direction: column;
+ gap: 0.8rem;
+ margin-bottom: 2rem;
+}
+
+.summary-item {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0.5rem 0;
+ border-bottom: 1px solid #f1f3f4;
+}
+
+.summary-item.highlight {
+ background: linear-gradient(90deg, rgba(40, 167, 69, 0.1), transparent);
+ padding: 1rem;
+ border-radius: 8px;
+ border: 2px solid #28a745;
+ font-weight: 600;
+ margin: 0.5rem 0;
+}
+
+.summary-item .label {
+ font-weight: 600;
+ color: #666;
+}
+
+.summary-item .value {
+ font-weight: 700;
+ font-size: 1.1rem;
+}
+
+.summary-item .value.relief {
+ color: #28a745;
+}
+
+.summary-item .value.tax {
+ color: #dc3545;
+ font-size: 1.2rem;
+}
+
+.summary-item .value.net {
+ color: #28a745;
+ font-size: 1.2rem;
+}
+
+.tax-rates {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 1rem;
+ margin-bottom: 2rem;
+}
+
+.rate-item {
+ background: linear-gradient(45deg, #f8f9fa, #e9ecef);
+ padding: 1rem;
+ border-radius: 8px;
+ text-align: center;
+ border: 1px solid #dee2e6;
+}
+
+.rate-label {
+ display: block;
+ font-size: 0.9rem;
+ color: #666;
+ margin-bottom: 0.5rem;
+}
+
+.rate-value {
+ display: block;
+ font-size: 1.5rem;
+ font-weight: 700;
+ color: #495057;
+}
+
+.tax-breakdown {
+ border-top: 2px solid #f1f3f4;
+ padding-top: 1.5rem;
+}
+
+.tax-breakdown h3 {
+ color: #333;
+ margin-bottom: 1rem;
+ font-size: 1.2rem;
+}
+
+.breakdown-table {
+ display: flex;
+ flex-direction: column;
+ border: 1px solid #dee2e6;
+ border-radius: 8px;
+ overflow: hidden;
+}
+
+.breakdown-header, .breakdown-row {
+ display: grid;
+ grid-template-columns: 2fr 1fr 1.5fr 1.5fr;
+ gap: 1rem;
+ padding: 0.75rem;
+ align-items: center;
+}
+
+.breakdown-header {
+ background: linear-gradient(45deg, #667eea, #764ba2);
+ color: white;
+ font-weight: 600;
+ font-size: 0.9rem;
+}
+
+.breakdown-row {
+ border-bottom: 1px solid #f1f3f4;
+ font-size: 0.9rem;
+}
+
+.breakdown-row:nth-child(even) {
+ background: #f8f9fa;
+}
+
+.breakdown-row:last-child {
+ border-bottom: none;
+}
+
+.tax-brackets-info {
+ background: white;
+ border-radius: 12px;
+ padding: 2rem;
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
+ border: 1px solid rgba(255, 255, 255, 0.2);
+}
+
+.tax-brackets-info h3 {
+ color: #333;
+ margin-bottom: 1.5rem;
+ font-size: 1.4rem;
+ border-bottom: 2px solid #ffc107;
+ padding-bottom: 0.5rem;
+}
+
+.brackets-table {
+ display: flex;
+ flex-direction: column;
+ border: 1px solid #dee2e6;
+ border-radius: 8px;
+ overflow: hidden;
+}
+
+.brackets-header, .brackets-row {
+ display: grid;
+ grid-template-columns: 2fr 1fr;
+ gap: 1rem;
+ padding: 0.75rem;
+ align-items: center;
+}
+
+.brackets-header {
+ background: linear-gradient(45deg, #ffc107, #fd7e14);
+ color: white;
+ font-weight: 600;
+ font-size: 0.9rem;
+}
+
+.brackets-row {
+ border-bottom: 1px solid #f1f3f4;
+ font-size: 0.9rem;
+}
+
+.brackets-row:nth-child(even) {
+ background: #f8f9fa;
+}
+
+.brackets-row:last-child {
+ border-bottom: none;
+}
+
+@media (max-width: 768px) {
+ .income-tax-container {
+ padding: 1rem;
+ }
+
+ .tax-header h1 {
+ font-size: 2rem;
+ }
+
+ .relief-grid {
+ grid-template-columns: 1fr;
+ }
+
+ .button-group {
+ flex-direction: column;
+ }
+
+ .tax-rates {
+ grid-template-columns: 1fr;
+ }
+
+ .breakdown-header, .breakdown-row {
+ grid-template-columns: 1fr;
+ gap: 0.5rem;
+ text-align: center;
+ }
+
+ .brackets-header, .brackets-row {
+ grid-template-columns: 1fr;
+ gap: 0.5rem;
+ text-align: center;
+ }
+}
\ No newline at end of file
diff --git a/src/components/IncomeTax/IncomeTaxCalculator.js b/src/components/IncomeTax/IncomeTaxCalculator.js
new file mode 100644
index 0000000..08db887
--- /dev/null
+++ b/src/components/IncomeTax/IncomeTaxCalculator.js
@@ -0,0 +1,250 @@
+import { useState } from 'react';
+import './IncomeTaxCalculator.css';
+
+const IncomeTaxCalculator = () => {
+ const [income, setIncome] = useState('');
+ const [personalRelief, setPersonalRelief] = useState(9000);
+ const [spouseRelief, setSpouseRelief] = useState(0);
+ const [childRelief, setChildRelief] = useState(0);
+ const [educationRelief, setEducationRelief] = useState(0);
+ const [epfRelief, setEpfRelief] = useState(0);
+ const [results, setResults] = useState(null);
+
+ const taxBrackets = [
+ { min: 0, max: 5000, rate: 0 },
+ { min: 5001, max: 20000, rate: 1 },
+ { min: 20001, max: 35000, rate: 3 },
+ { min: 35001, max: 50000, rate: 6 },
+ { min: 50001, max: 70000, rate: 11 },
+ { min: 70001, max: 100000, rate: 19 },
+ { min: 100001, max: 400000, rate: 25 },
+ { min: 400001, max: 600000, rate: 26 },
+ { min: 600001, max: 2000000, rate: 28 },
+ { min: 2000001, max: Infinity, rate: 30 }
+ ];
+
+ const calculateTax = () => {
+ const grossIncome = parseFloat(income) || 0;
+ const totalRelief = personalRelief + spouseRelief + (childRelief * 2000) + educationRelief + epfRelief;
+ const taxableIncome = Math.max(0, grossIncome - totalRelief);
+
+ let tax = 0;
+ let breakdownData = [];
+
+ for (const bracket of taxBrackets) {
+ if (taxableIncome > bracket.min - 1) {
+ const taxableInBracket = Math.min(taxableIncome, bracket.max) - bracket.min + 1;
+ const taxInBracket = (taxableInBracket * bracket.rate) / 100;
+
+ if (taxInBracket > 0) {
+ tax += taxInBracket;
+ breakdownData.push({
+ range: bracket.max === Infinity ? `RM ${bracket.min.toLocaleString()}+` : `RM ${bracket.min.toLocaleString()} - RM ${bracket.max.toLocaleString()}`,
+ rate: bracket.rate,
+ taxableAmount: taxableInBracket,
+ taxAmount: taxInBracket
+ });
+ }
+ }
+ }
+
+ const netIncome = grossIncome - tax;
+ const effectiveRate = grossIncome > 0 ? (tax / grossIncome) * 100 : 0;
+ const marginalRate = taxBrackets.find(bracket =>
+ taxableIncome >= bracket.min - 1 && taxableIncome <= bracket.max
+ )?.rate || 0;
+
+ setResults({
+ grossIncome,
+ totalRelief,
+ taxableIncome,
+ tax,
+ netIncome,
+ effectiveRate,
+ marginalRate,
+ breakdown: breakdownData
+ });
+ };
+
+ const handleReset = () => {
+ setIncome('');
+ setPersonalRelief(9000);
+ setSpouseRelief(0);
+ setChildRelief(0);
+ setEducationRelief(0);
+ setEpfRelief(0);
+ setResults(null);
+ };
+
+ return (
+
+
+
🇲🇾 Malaysia Income Tax Calculator 2025
+
Calculate your Malaysian income tax liability for Assessment Year 2025
+
+
+
+
+
+
Income Information
+
+ Annual Gross Income (RM)
+ setIncome(e.target.value)}
+ placeholder="Enter your annual income"
+ className="income-input"
+ />
+
+
+
+
+
+
+
+ Calculate Tax
+
+
+ Reset
+
+
+
+
+
+ {results && (
+
+
Tax Calculation Results
+
+
+
+ Gross Income:
+ RM {results.grossIncome.toLocaleString()}
+
+
+ Total Relief:
+ -RM {results.totalRelief.toLocaleString()}
+
+
+ Taxable Income:
+ RM {results.taxableIncome.toLocaleString()}
+
+
+ Tax Payable:
+ RM {results.tax.toFixed(2)}
+
+
+ Net Income:
+ RM {results.netIncome.toFixed(2)}
+
+
+
+
+
+ Effective Tax Rate:
+ {results.effectiveRate.toFixed(2)}%
+
+
+ Marginal Tax Rate:
+ {results.marginalRate}%
+
+
+
+ {results.breakdown.length > 0 && (
+
+
Tax Breakdown by Bracket
+
+
+ Income Range
+ Rate
+ Taxable Amount
+ Tax
+
+ {results.breakdown.map((bracket, index) => (
+
+ {bracket.range}
+ {bracket.rate}%
+ RM {bracket.taxableAmount.toFixed(0)}
+ RM {bracket.taxAmount.toFixed(2)}
+
+ ))}
+
+
+ )}
+
+ )}
+
+
+
Malaysia Tax Brackets 2025
+
+
+ Income Range (RM)
+ Tax Rate
+
+ {taxBrackets.map((bracket, index) => (
+
+
+ {bracket.min === 0 ? '0' : bracket.min.toLocaleString()} - {' '}
+ {bracket.max === Infinity ? '2,000,000+' : bracket.max.toLocaleString()}
+
+ {bracket.rate}%
+
+ ))}
+
+
+
+
+
+ );
+};
+
+export default IncomeTaxCalculator;
\ No newline at end of file
diff --git a/src/components/Navbar.js b/src/components/Navbar.js
index 456ecc4..30634f4 100644
--- a/src/components/Navbar.js
+++ b/src/components/Navbar.js
@@ -18,6 +18,7 @@ function Navbar() {
Pathfinding
Game Theory
Project Calculator
+ Income Tax
AlgoCraft