Fee First 9th

 import React, { useState } from 'react';

import { Calculator, Receipt, IndianRupee, CheckSquare, Square, Users, TableProperties, AlertCircle, Printer } from 'lucide-react';


const feeData = {

  'GEN/OBC': {

    title: '9th - GEN/OBC',

    color: 'blue',

    items: [

      { id: 'gen_sci', name: 'Sci', amount: 5.00 },

      { id: 'gen_art', name: 'Art', amount: 2.00 },

      { id: 'gen_fan', name: 'Fan', amount: 20.00 },

      { id: 'gen_da', name: 'DA', amount: 1.00 },

      { id: 'gen_df', name: 'DF', amount: 10.00 },

      { id: 'gen_rr', name: 'RR', amount: 12.00 },

      { id: 'gen_game', name: 'Game', amount: 5.00 },

      { id: 'gen_scout', name: 'Scout', amount: 2.00 },

      { id: 'gen_rc', name: 'RC', amount: 1.00 },

      { id: 'gen_pbf', name: 'PBF', amount: 10.00 },

      { id: 'gen_av', name: 'AV', amount: 2.00 },

      { id: 'gen_mag', name: 'Mag', amount: 20.00 },

      { id: 'gen_exam', name: 'Exam', amount: 50.00 },

      { id: 'gen_jalpan', name: 'Jalpan', amount: 10.00 },

      { id: 'gen_icard', name: 'I.card', amount: 10.00 },

      { id: 'gen_pragti', name: 'Pragti Patra', amount: 5.00 },

      { id: 'gen_regi', name: 'Regi', amount: 50.00 },

    ]

  },

  'SC': {

    title: '9th - SC',

    color: 'purple',

    items: [

      { id: 'sc_sci', name: 'Sci', amount: 5.00 },

      { id: 'sc_art', name: 'Art', amount: 2.00 },

      { id: 'sc_fan', name: 'Fan', amount: 20.00 },

      { id: 'sc_scout', name: 'Scout', amount: 2.00 },

      { id: 'sc_rc', name: 'RC', amount: 1.00 },

      { id: 'sc_pbf', name: 'PBF', amount: 10.00 },

      { id: 'sc_mag', name: 'Mag', amount: 20.00 },

      { id: 'sc_exam', name: 'Exam', amount: 50.00 },

      { id: 'sc_jalpan', name: 'Jalpan', amount: 10.00 },

      { id: 'sc_icard', name: 'I.card', amount: 10.00 },

      { id: 'sc_pragti', name: 'Pragti Patra', amount: 5.00 },

      { id: 'sc_regi', name: 'Regi', amount: 50.00 },

    ]

  }

};


// Safe Tailwind Color Classes for dynamic rendering

const colors = {

  'GEN/OBC': { bg: 'bg-blue-50', border: 'border-blue-200', text: 'text-blue-900', check: 'text-blue-600' },

  'SC': { bg: 'bg-purple-50', border: 'border-purple-200', text: 'text-purple-900', check: 'text-purple-600' }

};


// Initialize all items as selected

const initialSelectedItems = {

  'GEN/OBC': new Set(feeData['GEN/OBC'].items.map(i => i.id)),

  'SC': new Set(feeData['SC'].items.map(i => i.id))

};


// All unique item names for the summary table

const allUniqueItemNames = [...new Set([

  ...feeData['GEN/OBC'].items.map(i => i.name),

  ...feeData['SC'].items.map(i => i.name),

  'Fine (Manual)'

])];


export default function App() {

  const [studentCounts, setStudentCounts] = useState({ 'GEN/OBC': '', 'SC': '' });

  const [selectedItems, setSelectedItems] = useState(initialSelectedItems);

  const [fines, setFines] = useState({ 'GEN/OBC': '', 'SC': '' }); 

  const [printHint, setPrintHint] = useState(false);


  const handlePrint = () => {

    try {

      window.print();

    } catch (e) {

      console.log("Print blocked by environment", e);

    }

    // Agar environment print block karta hai, toh user ko alternative rasta dikhayein

    setPrintHint(true);

    setTimeout(() => setPrintHint(false), 6000);

  };


  const handleCountChange = (category, value) => {

    const num = value === '' ? '' : parseInt(value, 10);

    setStudentCounts(prev => ({ ...prev, [category]: isNaN(num) && value !== '' ? prev[category] : num }));

  };


  const handleFineChange = (category, value) => {

    setFines(prev => ({ ...prev, [category]: value }));

  };


  const toggleItem = (category, id) => {

    const newSelected = new Set(selectedItems[category]);

    if (newSelected.has(id)) {

      newSelected.delete(id);

    } else {

      newSelected.add(id);

    }

    setSelectedItems(prev => ({ ...prev, [category]: newSelected }));

  };


  const calculatePerStudent = (category) => {

    let total = 0;

    feeData[category].items.forEach(item => {

      if (selectedItems[category].has(item.id)) {

        total += item.amount;

      }

    });

    const fineAmount = parseFloat(fines[category]) || 0;

    return total + fineAmount;

  };


  const perStudentGen = calculatePerStudent('GEN/OBC');

  const perStudentSc = calculatePerStudent('SC');

  

  const countGen = studentCounts['GEN/OBC'] || 0;

  const countSc = studentCounts['SC'] || 0;


  const totalGenFee = perStudentGen * countGen;

  const totalScFee = perStudentSc * countSc;

  const grandTotal = totalGenFee + totalScFee;


  // Generate data for Combined Summary Table

  const getSummaryData = () => {

    const rows = [];

    allUniqueItemNames.forEach(name => {

      let genAmount = 0;

      let scAmount = 0;


      if (name === 'Fine (Manual)') {

        const genFine = parseFloat(fines['GEN/OBC']) || 0;

        const scFine = parseFloat(fines['SC']) || 0;

        genAmount = genFine * countGen;

        scAmount = scFine * countSc;

      } else {

        const genItem = feeData['GEN/OBC'].items.find(i => i.name === name);

        if (genItem && selectedItems['GEN/OBC'].has(genItem.id)) {

          genAmount = genItem.amount * countGen;

        }


        const scItem = feeData['SC'].items.find(i => i.name === name);

        if (scItem && selectedItems['SC'].has(scItem.id)) {

          scAmount = scItem.amount * countSc;

        }

      }


      if (genAmount > 0 || scAmount > 0) {

        rows.push({ name, genAmount, scAmount, total: genAmount + scAmount });

      }

    });

    return rows;

  };


  const summaryRows = getSummaryData();


  const FeeItem = ({ category, item, count }) => {

    const isSelected = selectedItems[category].has(item.id);

    const theme = colors[category];


    return (

      <div 

        className={`flex items-center justify-between p-2 rounded border cursor-pointer transition-colors ${

          isSelected 

            ? `${theme.bg} ${theme.border} ${theme.text}` 

            : 'bg-gray-50 border-gray-200 text-gray-400 hover:bg-gray-100'

        }`}

        onClick={() => toggleItem(category, item.id)}

      >

        <div className="flex items-center space-x-2">

          {isSelected ? (

            <CheckSquare className={`w-4 h-4 ${theme.check}`} />

          ) : (

            <Square className="w-4 h-4" />

          )}

          <span className="font-medium text-sm">{item.name}</span>

        </div>

        <div className="text-right">

          {count > 0 ? (

            <div className="flex flex-col items-end">

              <span className="font-semibold text-sm">₹{(item.amount * count).toFixed(2)}</span>

              <span className={`text-[10px] ${isSelected ? `${theme.check} opacity-80` : 'text-gray-400'}`}>

                ₹{item.amount.toFixed(2)} × {count}

              </span>

            </div>

          ) : (

            <span className="font-semibold text-sm">₹{item.amount.toFixed(2)}</span>

          )}

        </div>

      </div>

    );

  };


  const FineItem = ({ category, count }) => {

    const fineVal = parseFloat(fines[category]) || 0;

    return (

      <div className="flex items-center justify-between p-2 rounded border bg-amber-50 border-amber-200 mt-2">

        <div className="flex items-center space-x-2 text-amber-800">

          <AlertCircle className="w-4 h-4" />

          <span className="font-medium text-sm">Fine (Manual)</span>

        </div>

        <div className="flex flex-col items-end">

          <div className="flex items-center space-x-1">

            <span className="text-amber-700 text-sm font-medium">₹</span>

            <input

              type="number"

              min="0"

              placeholder="0"

              value={fines[category]}

              onChange={(e) => handleFineChange(category, e.target.value)}

              className="w-16 p-1 border border-amber-300 rounded text-right text-sm font-semibold outline-none focus:border-amber-500 bg-white print:border-none print:bg-transparent print:p-0"

            />

          </div>

          {count > 0 && fineVal > 0 && (

            <span className="text-[10px] text-amber-700 mt-1">

              ₹{fineVal.toFixed(2)} × {count} = ₹{(fineVal * count).toFixed(2)}

            </span>

          )}

        </div>

      </div>

    );

  };


  return (

    <div className="min-h-screen bg-gray-100 p-2 sm:p-4 md:p-8 font-sans pb-32 print:bg-white print:p-0 print:pb-0">

      <div className="max-w-6xl mx-auto space-y-6 print:space-y-4">

        

        {/* Header */}

        <div className="bg-white rounded-2xl shadow-sm border border-gray-200 p-6 text-center relative print:border-none print:shadow-none print:p-0 print:mb-8">

          <div className="absolute top-4 right-4 sm:top-6 sm:right-6 print:hidden flex flex-col items-end z-10">

            <button 

              onClick={handlePrint}

              className="flex items-center bg-gray-900 text-white px-4 py-2 rounded-xl text-sm font-semibold hover:bg-gray-800 transition-colors shadow-md"

            >

              <Printer className="w-4 h-4 mr-2" />

              Print PDF

            </button>

            {printHint && (

              <div className="mt-2 text-xs text-red-600 bg-red-50 p-2 rounded-lg border border-red-200 w-44 text-right shadow-sm">

                Agar button kaam na kare, toh kripya browser ke menu se <b>Print</b> chunein ya <b>Ctrl+P</b> dabayein.

              </div>

            )}

          </div>

          <div className="flex justify-center mb-2 text-blue-600 print:hidden mt-10 sm:mt-0">

            <Calculator className="w-10 h-10" />

          </div>

          <h1 className="text-2xl md:text-3xl font-bold text-gray-800 tracking-wide">Fee Collection Calculator</h1>

          <p className="text-gray-500 mt-1">Class 9th (2021-22) - GEN/OBC & SC</p>

        </div>


        {/* Grid for Both Categories */}

        <div className="grid grid-cols-1 lg:grid-cols-2 gap-6">

          

          {/* GEN/OBC Card */}

          <div className="bg-white rounded-2xl shadow-sm border-t-4 border-blue-500 flex flex-col print:border-t-2 print:border-gray-800 print:shadow-none">

            <div className="p-5 flex-grow">

              <h2 className="text-xl font-bold text-gray-800 mb-4 flex items-center">

                <Users className="w-6 h-6 mr-2 text-blue-500 print:text-gray-800" />

                GEN / OBC

              </h2>

              

              <div className="mb-4">

                <label className="block text-sm font-medium text-gray-600 mb-1 print:hidden">Student ki Sankhya (Count)</label>

                <div className="hidden print:block text-sm font-medium text-gray-600 mb-1">Total Students:</div>

                <input 

                  type="number"

                  min="0"

                  value={studentCounts['GEN/OBC']}

                  onChange={(e) => handleCountChange('GEN/OBC', e.target.value)}

                  placeholder="0"

                  className="w-full text-xl p-3 border-2 border-gray-200 rounded-xl focus:border-blue-500 focus:ring-0 outline-none transition-colors print:border-none print:p-0 print:text-2xl print:font-bold print:text-gray-900"

                />

              </div>


              <div className="bg-blue-50 rounded-xl p-4 flex justify-between items-center mb-6 print:bg-white print:border print:border-gray-300">

                <div>

                  <p className="text-xs text-blue-600 font-bold uppercase tracking-wide print:text-gray-600">Prati Student</p>

                  <p className="text-xl font-bold text-blue-900 print:text-gray-900">₹{perStudentGen.toFixed(2)}</p>

                </div>

                <div className="text-right">

                  <p className="text-xs text-blue-600 font-bold uppercase tracking-wide print:text-gray-600">Kul (Total)</p>

                  <p className="text-2xl font-black text-blue-700 print:text-gray-900">₹{totalGenFee.toFixed(2)}</p>

                </div>

              </div>


              <div className="border-t pt-4">

                <h3 className="text-sm font-bold text-gray-500 uppercase mb-3">Sabhi Mad (Fee Items)</h3>

                <div className="grid grid-cols-1 sm:grid-cols-2 gap-2">

                  {feeData['GEN/OBC'].items.map(item => (

                    <FeeItem key={item.id} category="GEN/OBC" item={item} count={countGen} />

                  ))}

                </div>

                <FineItem category="GEN/OBC" count={countGen} />

              </div>

            </div>

          </div>


          {/* SC Card */}

          <div className="bg-white rounded-2xl shadow-sm border-t-4 border-purple-500 flex flex-col print:border-t-2 print:border-gray-800 print:shadow-none">

            <div className="p-5 flex-grow">

              <h2 className="text-xl font-bold text-gray-800 mb-4 flex items-center">

                <Users className="w-6 h-6 mr-2 text-purple-500 print:text-gray-800" />

                SC

              </h2>

              

              <div className="mb-4">

                <label className="block text-sm font-medium text-gray-600 mb-1 print:hidden">Student ki Sankhya (Count)</label>

                <div className="hidden print:block text-sm font-medium text-gray-600 mb-1">Total Students:</div>

                <input 

                  type="number"

                  min="0"

                  value={studentCounts['SC']}

                  onChange={(e) => handleCountChange('SC', e.target.value)}

                  placeholder="0"

                  className="w-full text-xl p-3 border-2 border-gray-200 rounded-xl focus:border-purple-500 focus:ring-0 outline-none transition-colors print:border-none print:p-0 print:text-2xl print:font-bold print:text-gray-900"

                />

              </div>


              <div className="bg-purple-50 rounded-xl p-4 flex justify-between items-center mb-6 print:bg-white print:border print:border-gray-300">

                <div>

                  <p className="text-xs text-purple-600 font-bold uppercase tracking-wide print:text-gray-600">Prati Student</p>

                  <p className="text-xl font-bold text-purple-900 print:text-gray-900">₹{perStudentSc.toFixed(2)}</p>

                </div>

                <div className="text-right">

                  <p className="text-xs text-purple-600 font-bold uppercase tracking-wide print:text-gray-600">Kul (Total)</p>

                  <p className="text-2xl font-black text-purple-700 print:text-gray-900">₹{totalScFee.toFixed(2)}</p>

                </div>

              </div>


              <div className="border-t pt-4">

                <h3 className="text-sm font-bold text-gray-500 uppercase mb-3">Sabhi Mad (Fee Items)</h3>

                <div className="grid grid-cols-1 sm:grid-cols-2 gap-2">

                  {feeData['SC'].items.map(item => (

                    <FeeItem key={item.id} category="SC" item={item} count={countSc} />

                  ))}

                </div>

                <FineItem category="SC" count={countSc} />

              </div>

            </div>

          </div>


        </div>


        {/* Combined Summary Section */}

        {summaryRows.length > 0 && (

          <div className="bg-white rounded-2xl shadow-sm border border-gray-200 overflow-hidden print:shadow-none print:border-gray-300 print:mt-8 break-inside-avoid">

            <div className="p-5 border-b border-gray-200 bg-gray-50 flex items-center print:bg-white">

              <TableProperties className="w-6 h-6 mr-3 text-indigo-600 print:hidden" />

              <h2 className="text-lg md:text-xl font-bold text-gray-800">Sabhi Mado ka Combined Total</h2>

            </div>

            

            <div className="overflow-x-auto">

              <table className="w-full text-left border-collapse min-w-[600px] print:min-w-full">

                <thead>

                  <tr className="bg-gray-100 text-gray-600 text-sm uppercase tracking-wider print:bg-white print:border-b-2 print:border-gray-800">

                    <th className="p-4 border-b font-semibold">Mad (Item)</th>

                    <th className="p-4 border-b font-semibold text-right">GEN/OBC Total</th>

                    <th className="p-4 border-b font-semibold text-right">SC Total</th>

                    <th className="p-4 border-b font-bold text-right text-gray-900">Kul (Combined Total)</th>

                  </tr>

                </thead>

                <tbody className="divide-y divide-gray-100 print:divide-gray-300">

                  {summaryRows.map((row, idx) => (

                    <tr key={idx} className="hover:bg-indigo-50/30 transition-colors">

                      <td className="p-4 font-medium text-gray-700">{row.name}</td>

                      <td className="p-4 text-right text-gray-600">₹{row.genAmount.toFixed(2)}</td>

                      <td className="p-4 text-right text-gray-600">₹{row.scAmount.toFixed(2)}</td>

                      <td className="p-4 text-right font-bold text-gray-800">₹{row.total.toFixed(2)}</td>

                    </tr>

                  ))}

                </tbody>

                <tfoot>

                  <tr className="bg-gray-50 print:bg-white print:border-t-2 print:border-gray-800">

                    <td className="p-4 font-bold text-gray-800 text-right uppercase text-sm">Final Amount</td>

                    <td className="p-4 font-bold text-blue-600 print:text-gray-900 text-right text-lg">₹{totalGenFee.toFixed(2)}</td>

                    <td className="p-4 font-bold text-purple-600 print:text-gray-900 text-right text-lg">₹{totalScFee.toFixed(2)}</td>

                    <td className="p-4 font-black text-green-600 print:text-gray-900 text-right text-xl">₹{grandTotal.toFixed(2)}</td>

                  </tr>

                </tfoot>

              </table>

            </div>

          </div>

        )}


      </div>


      {/* Fixed Bottom Grand Total Bar */}

      <div className="fixed bottom-0 left-0 right-0 bg-gray-900 text-white shadow-2xl border-t border-gray-800 z-50 print:hidden">

        <div className="max-w-6xl mx-auto p-4 sm:px-6 md:px-8 flex flex-row items-center justify-between">

          <div className="flex items-center space-x-3 sm:space-x-4">

            <div className="bg-gray-800 p-2 sm:p-3 rounded-full hidden sm:block">

              <Receipt className="w-6 h-6 sm:w-8 sm:h-8 text-green-400" />

            </div>

            <div>

              <h2 className="text-lg sm:text-2xl font-bold">Grand Total (Sabhi)</h2>

              <p className="text-gray-400 text-xs sm:text-sm">

                Total Students: {countGen + countSc} 

                <span className="hidden sm:inline"> ({countGen} GEN/OBC, {countSc} SC)</span>

              </p>

            </div>

          </div>

          <div className="flex flex-col items-end">

            <div className="flex items-center text-2xl sm:text-4xl md:text-5xl font-black text-green-400">

              <IndianRupee className="w-5 h-5 sm:w-8 sm:h-8 mr-1 sm:mr-2" />

              {grandTotal.toLocaleString('en-IN', { minimumFractionDigits: 2 })}

            </div>

          </div>

        </div>

      </div>

      

    </div>

  );

}