diff --git a/src/App.tsx b/src/App.tsx index 663a6a9..079edff 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -3,6 +3,7 @@ import { IonReactRouter } from "@ionic/react-router"; import { Route, Redirect } from "react-router-dom"; import Home from "./pages/Home"; import MeshKitPage from "./pages/MeshKit"; +import { StoreProvider } from "./contexts/StoreContext"; /* Core CSS required for Ionic components to work properly */ import "@ionic/react/css/core.css"; @@ -26,21 +27,23 @@ import "./theme/variables.css"; setupIonicReact(); const App: React.FC = () => ( - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + ); export default App; diff --git a/src/components/Dashboard/Dashboard.tsx b/src/components/Dashboard/Dashboard.tsx index dcbed8d..01d0629 100644 --- a/src/components/Dashboard/Dashboard.tsx +++ b/src/components/Dashboard/Dashboard.tsx @@ -8,21 +8,24 @@ import { documentTextOutline, cloudUploadOutline, cloudDownloadOutline, shareSocialOutline, trashOutline, addCircleOutline, serverOutline, hardwareChipOutline, openOutline, timeOutline, statsChartOutline, searchOutline, documentOutline } from "ionicons/icons"; -import { Local, File as LocalFile, BackupRecord, ActivityLog, AppMetrics } from "../Storage/LocalStorage"; +import { File as LocalFile, BackupRecord, ActivityLog, AppMetrics } from "../Storage/LocalStorage"; import { backupInvoiceToIPFS, restoreInvoiceFromIPFS, testConnection } from "../../services/MeshkitService"; import { BackupSuccessModal } from "../Modals/BackupSuccessModal"; import { RestoreSuccessModal } from "../Modals/RestoreSuccessModal"; import * as AppGeneral from "../socialcalc/index.js"; import { useHistory } from "react-router"; import { DATA } from "../../app-data.js"; +import { useStore } from "../../contexts/StoreContext"; +import { useInvoice } from "../../contexts/InvoiceContext"; interface DashboardProps { - store: Local; onOpenFile: (key: string, billType: number) => void; - currentBillType: number; } -const Dashboard: React.FC = ({ store, onOpenFile, currentBillType }) => { +const Dashboard: React.FC = ({ onOpenFile }) => { + const store = useStore(); + const { billType } = useInvoice(); + const [fileList, setFileList] = useState<{ [key: string]: any }>({}); const [backupHistory, setBackupHistory] = useState([]); const [activityLogs, setActivityLogs] = useState([]); @@ -204,7 +207,7 @@ const Dashboard: React.FC = ({ store, onOpenFile, currentBillTyp return; } const content = encodeURIComponent(JSON.stringify(DATA["home"][AppGeneral.getDeviceType()]["msc"])); - const file = new LocalFile(new Date().toString(), new Date().toString(), content, filename, currentBillType); + const file = new LocalFile(new Date().toString(), new Date().toString(), content, filename, billType); await store._saveFile(file); await store._incrementMetric('invoicesCreated'); await store._logActivity({ type: 'CREATE', description: `Created new invoice ${filename}` }); @@ -316,12 +319,12 @@ const Dashboard: React.FC = ({ store, onOpenFile, currentBillTyp handleBackup(key)}> Backup - {fileList[key].backedUp && ( + {fileList[key].backedUp && fileList[key].cid && ( handleRestore(fileList[key].cid, key)}> Restore )} - {fileList[key].backedUp && ( + {fileList[key].backedUp && fileList[key].cid && ( handleShare(fileList[key].cid)}> Share diff --git a/src/components/Files/Files.css b/src/components/Files/Files.css deleted file mode 100644 index 53a9878..0000000 --- a/src/components/Files/Files.css +++ /dev/null @@ -1,30 +0,0 @@ -.file ul{ - list-style: none; - overflow-y: scroll; height:400px; -} - -.file li{ - font-weight: bold; - cursor: pointer; - border-bottom: 0.1rem solid #e1e1e1; - padding: 2px 2px; - text-align: left; -} - -.file span{ - font-size: 12px; - color: #9b4dca; - margin-right: 20px; -} - -/* -td:first-child, -th:first-child { - padding-left: 0; -} - -td:last-child, -th:last-child { - padding-right: 0; -} -606c76*/ \ No newline at end of file diff --git a/src/components/Files/Files.tsx b/src/components/Files/Files.tsx deleted file mode 100644 index b8fcb25..0000000 --- a/src/components/Files/Files.tsx +++ /dev/null @@ -1,346 +0,0 @@ -import React, { useState, useEffect } from "react"; -import "./Files.css"; -import * as AppGeneral from "../socialcalc/index.js"; -import { DATA } from "../../app-data.js"; -import { File as LocalFile, Local, BackupRecord } from "../Storage/LocalStorage"; -import { - IonIcon, - IonModal, - IonItem, - IonButton, - IonList, - IonLabel, - IonAlert, - IonItemGroup, - IonActionSheet, - IonBadge, - IonToast, - IonSpinner, - ActionSheetButton, - IonHeader, - IonToolbar, - IonTitle, - IonContent, - IonButtons -} from "@ionic/react"; -import { fileTrayFull, ellipsisVertical, cloudUploadOutline, cloudDownloadOutline, shareSocialOutline, trash, folderOpenOutline, timeOutline } from "ionicons/icons"; -import { backupInvoiceToIPFS, restoreInvoiceFromIPFS } from "../../services/MeshkitService"; - -const Files: React.FC<{ - store: Local; - file: string; - updateSelectedFile: Function; - updateBillType: Function; -}> = (props) => { - const [modal, setModal] = useState(null); - const [listFiles, setListFiles] = useState(false); - const [showAlertDelete, setShowAlertDelete] = useState(false); - const [currentKey, setCurrentKey] = useState(null); - - const [fileList, setFileList] = useState<{ [key: string]: any }>({}); - - const [actionSheetOpen, setActionSheetOpen] = useState(false); - const [selectedActionFile, setSelectedActionFile] = useState(null); - - const [toastMessage, setToastMessage] = useState(""); - const [showToast, setShowToast] = useState(false); - const [isLoading, setIsLoading] = useState(false); - - const [showHistoryModal, setShowHistoryModal] = useState(false); - const [backupHistory, setBackupHistory] = useState([]); - - const loadFiles = async () => { - const files = await props.store._getAllFiles(); - setFileList(files); - }; - - const loadHistory = async () => { - const history = await props.store._getBackupHistory(); - setBackupHistory(history.reverse()); // Show newest first - }; - - useEffect(() => { - if (listFiles) { - loadFiles(); - } - }, [listFiles]); - - const displayToast = (msg: string) => { - setToastMessage(msg); - setShowToast(true); - }; - - const editFile = (key: string) => { - props.store._getFile(key).then((data: any) => { - AppGeneral.viewFile(key, decodeURIComponent(data.content)); - props.updateSelectedFile(key); - props.updateBillType(data.billType); - setListFiles(false); - }); - }; - - const deleteFile = (key: string) => { - setShowAlertDelete(true); - setCurrentKey(key); - }; - - const loadDefault = () => { - const msc = DATA["home"][AppGeneral.getDeviceType()]["msc"]; - AppGeneral.viewFile("default", JSON.stringify(msc)); - props.updateSelectedFile("default"); - }; - - const _formatDate = (date: string) => { - if (!date) return ""; - return new Date(date).toLocaleString(); - }; - - const handleBackup = async (key: string) => { - setIsLoading(true); - try { - const data: any = await props.store._getFile(key); - const record = await backupInvoiceToIPFS({ - name: key, - created: data.created, - modified: new Date().toString(), - billType: data.billType, - content: data.content, - }); - - const file = new LocalFile( - data.created, - data.modified, - data.content, - key, - data.billType, - true, - record.cid, - new Date().toISOString() - ); - await props.store._saveFile(file); - await props.store._addBackupHistory({ - cid: record.cid, - timestamp: new Date().toISOString(), - name: key - }); - displayToast("Backup successful!"); - loadFiles(); - } catch (error) { - displayToast(error instanceof Error ? error.message : "Backup failed"); - } finally { - setIsLoading(false); - } - }; - - const handleRestore = async (key: string, cid: string) => { - setIsLoading(true); - try { - const backup = await restoreInvoiceFromIPFS(cid); - const file = new LocalFile( - backup.created || new Date().toString(), - backup.modified || new Date().toString(), - backup.content, - key, - backup.billType, - true, - cid, - new Date().toISOString() - ); - await props.store._saveFile(file); - displayToast(`Restored IPFS version of ${key}`); - loadFiles(); - editFile(key); // Automatically open the restored version - } catch (error) { - displayToast("Restore failed: " + (error instanceof Error ? error.message : String(error))); - } finally { - setIsLoading(false); - } - }; - - const handleShare = async (cid: string) => { - try { - await navigator.clipboard.writeText(`CID: ${cid}\nGateway: https://gateway.pinata.cloud/ipfs/${cid}`); - displayToast("CID & Gateway Link copied to clipboard!"); - } catch (err) { - displayToast("Failed to copy link"); - } - }; - - const getActionSheetButtons = (): ActionSheetButton[] => { - if (!selectedActionFile) return []; - - const fileData = fileList[selectedActionFile]; - const isBackedUp = fileData?.backedUp && fileData?.cid; - - const buttons: ActionSheetButton[] = [ - { - text: 'Open', - icon: folderOpenOutline, - handler: () => editFile(selectedActionFile) - }, - { - text: 'Backup to IPFS', - icon: cloudUploadOutline, - handler: () => handleBackup(selectedActionFile) - } - ]; - - if (isBackedUp) { - buttons.push({ - text: 'Restore (Overwrite Local)', - icon: cloudDownloadOutline, - handler: () => handleRestore(selectedActionFile, fileData.cid) - }); - buttons.push({ - text: 'Share', - icon: shareSocialOutline, - handler: () => handleShare(fileData.cid) - }); - } - - buttons.push({ - text: 'Delete', - role: 'destructive', - icon: trash, - handler: () => deleteFile(selectedActionFile) - }); - - buttons.push({ - text: 'Cancel', - role: 'cancel', - handler: () => {} - }); - - return buttons; - }; - - const buildModalContent = () => { - const fileElements = Object.keys(fileList).map((key) => { - const data = fileList[key]; - return ( - - { setSelectedActionFile(key); setActionSheetOpen(true); }}> - - {key} - {_formatDate(data.modified)} - - {data.backedUp ? ( - Backed Up - ) : ( - Not Backed Up - )} - - - - ); - }); - - return ( - setListFiles(false)}> - - - Files - - { loadHistory(); setShowHistoryModal(true); }}> - - - setListFiles(false)}>Close - - - - - {isLoading && } - {fileElements} - - setActionSheetOpen(false)} - header={`Actions for ${selectedActionFile}`} - buttons={getActionSheetButtons()} - /> - - setShowHistoryModal(false)}> - - - Backup History - - setShowHistoryModal(false)}>Close - - - - - {backupHistory.length === 0 ? ( - No backup history available. - ) : ( - - {backupHistory.map((record, index) => ( - - - {record.name} - {_formatDate(record.timestamp)} - {record.cid} - - handleShare(record.cid)}> - - - - ))} - - )} - - - - - - ); - }; - - useEffect(() => { - setModal(buildModalContent()); - }, [listFiles, fileList, actionSheetOpen, isLoading, showHistoryModal, backupHistory]); - - return ( - - { - setListFiles(true); - }} - /> - {modal} - setShowAlertDelete(false)} - header="Delete file" - message={"Do you want to delete the " + currentKey + " file?"} - buttons={[ - { text: "No", role: "cancel" }, - { - text: "Yes", - handler: () => { - if (currentKey) { - props.store._deleteFile(currentKey); - loadDefault(); - setCurrentKey(null); - loadFiles(); // Refresh list after delete - } - }, - }, - ]} - /> - setShowToast(false)} - message={toastMessage} - duration={3000} - position="bottom" - /> - - ); -}; - -export default Files; diff --git a/src/components/Menu/Menu.tsx b/src/components/Menu/Menu.tsx index 0a861ae..fb06be7 100644 --- a/src/components/Menu/Menu.tsx +++ b/src/components/Menu/Menu.tsx @@ -1,6 +1,6 @@ import React, { useState } from "react"; import * as AppGeneral from "../socialcalc/index.js"; -import { File, Local } from "../Storage/LocalStorage"; +import { File } from "../Storage/LocalStorage"; import { isPlatform, IonToast } from "@ionic/react"; import { EmailComposer } from "capacitor-email-composer"; import { Printer } from "@ionic-native/printer"; @@ -9,15 +9,13 @@ import { saveOutline, save, mail, print, cloudUploadOutline, cloudDownloadOutlin import { APP_NAME } from "../../app-data.js"; import { backupInvoiceToIPFS, restoreInvoiceFromIPFS } from "../../services/MeshkitService"; import { BackupSuccessModal } from "../Modals/BackupSuccessModal"; +import { useStore } from "../../contexts/StoreContext"; +import { useInvoice } from "../../contexts/InvoiceContext"; + +const Menu: React.FC = () => { + const store = useStore(); + const { selectedFile, setSelectedFile, billType, showMenu, setShowMenu } = useInvoice(); -const Menu: React.FC<{ - showM: boolean; - setM: Function; - file: string; - updateSelectedFile: Function; - store: Local; - bT: number; -}> = (props) => { const [showAlert1, setShowAlert1] = useState(false); const [showAlert2, setShowAlert2] = useState(false); const [showAlert3, setShowAlert3] = useState(false); @@ -34,8 +32,7 @@ const Menu: React.FC<{ const [showAlertRestoreSuccess, setShowAlertRestoreSuccess] = useState(false); const [showAlertRestoreError, setShowAlertRestoreError] = useState(false); - /* Utility functions */ - const _validateName = async (filename) => { + const _validateName = async (filename: string) => { filename = filename.trim(); if (filename === "default" || filename === "Untitled") { setToastMessage("Cannot update default file!"); @@ -49,22 +46,20 @@ const Menu: React.FC<{ } else if (/^[a-zA-Z0-9- ]*$/.test(filename) === false) { setToastMessage("Special Characters cannot be used"); return false; - } else if (await props.store._checkKey(filename)) { + } else if (await store._checkKey(filename)) { setToastMessage("Filename already exists"); return false; } return true; }; - const getCurrentFileName = () => { - return props.file; - }; - const _formatString = (filename) => { - /* Remove whitespaces */ + + const _formatString = (filename: string) => { while (filename.indexOf(" ") !== -1) { filename = filename.replace(" ", ""); } return filename; }; + const doPrint = () => { if (isPlatform("hybrid")) { const printer = Printer; @@ -72,29 +67,33 @@ const Menu: React.FC<{ } else { const content = AppGeneral.getCurrentHTMLContent(); const printWindow = window.open("/printwindow", "Print Invoice"); - printWindow.document.write(content); - printWindow.print(); + if (printWindow) { + printWindow.document.write(content); + printWindow.print(); + } } }; - const doSave = () => { - if (props.file === "default") { + + const doSave = async () => { + if (selectedFile === "default") { setShowAlert1(true); return; } const content = encodeURIComponent(AppGeneral.getSpreadsheetContent()); - const data = props.store._getFile(props.file); + const data = await store._getFile(selectedFile); const file = new File( - (data as any).created, + data.created, new Date().toString(), content, - props.file, - props.bT + selectedFile, + billType ); - props.store._saveFile(file); - props.updateSelectedFile(props.file); + await store._saveFile(file); + setSelectedFile(selectedFile); setShowAlert2(true); }; - const doSaveAs = async (filename) => { + + const doSaveAs = async (filename: string) => { if (filename) { if (await _validateName(filename)) { const content = encodeURIComponent(AppGeneral.getSpreadsheetContent()); @@ -103,71 +102,69 @@ const Menu: React.FC<{ new Date().toString(), content, filename, - props.bT + billType ); - props.store._saveFile(file); - props.updateSelectedFile(filename); + await store._saveFile(file); + setSelectedFile(filename); setShowAlert4(true); } else { setShowToast1(true); } } }; + const doBackupToIPFS = async () => { - if (props.file === "default") { + if (selectedFile === "default") { setShowAlertBackupMissingFile(true); return; } try { - const data = await props.store._getFile(props.file); + const data = await store._getFile(selectedFile); const content = encodeURIComponent(AppGeneral.getSpreadsheetContent()); const record = await backupInvoiceToIPFS({ - name: props.file, - created: (data as any).created, + name: selectedFile, + created: data.created, modified: new Date().toString(), - billType: props.bT, + billType: billType, content, }); setBackupCid(record.cid); - - // Update local file metadata + const file = new File( - (data as any).created, - (data as any).modified, // Keep original modified date - (data as any).content, - props.file, - props.bT, - true, // backedUp + data.created, + data.modified, + data.content, + selectedFile, + billType, + true, record.cid, new Date().toISOString() ); - await props.store._saveFile(file); - - // Add to backup history - await props.store._addBackupHistory({ + await store._saveFile(file); + + await store._addBackupHistory({ cid: record.cid, timestamp: new Date().toISOString(), - name: props.file + name: selectedFile }); - } catch (error) { setBackupErrorMessage(error instanceof Error ? error.message : String(error)); setShowAlertBackupError(true); } }; - - const doRestoreFromIPFS = async (cid) => { + + const doRestoreFromIPFS = async (cid: string) => { if (!cid) return; try { const backup = await restoreInvoiceFromIPFS(cid); let filename = backup.name; - + let counter = 1; - while (await props.store._checkKey(filename)) { + while (await store._checkKey(filename)) { filename = `${backup.name}_restored_${counter}`; counter++; } - + const file = new File( backup.created || new Date().toString(), new Date().toString(), @@ -175,10 +172,10 @@ const Menu: React.FC<{ filename, backup.billType ); - - await props.store._saveFile(file); + + await store._saveFile(file); AppGeneral.viewFile(filename, decodeURIComponent(backup.content)); - props.updateSelectedFile(filename); + setSelectedFile(filename); setShowAlertRestoreSuccess(true); } catch (error) { setBackupErrorMessage(error instanceof Error ? error.message : String(error)); @@ -203,13 +200,14 @@ const Menu: React.FC<{ alert("This Functionality works on Anroid/IOS devices"); } }; + return ( props.setM()} + isOpen={showMenu} + onDidDismiss={() => setShowMenu(false)} buttons={[ { text: "Save", @@ -260,7 +258,7 @@ const Menu: React.FC<{ isOpen={showAlert1} onDidDismiss={() => setShowAlert1(false)} header="Alert Message" - message={"Cannot update " + getCurrentFileName() + " file!"} + message={"Cannot update " + selectedFile + " file!"} buttons={["Ok"]} /> setShowAlert2(false)} header="Save" - message={"File " + getCurrentFileName() + " updated successfully"} + message={"File " + selectedFile + " updated successfully"} buttons={["Ok"]} /> setShowAlert4(false)} header="Save As" - message={"File " + getCurrentFileName() + " saved successfully"} + message={"File " + selectedFile + " saved successfully"} buttons={["Ok"]} /> = (props) => { +const NewFile: React.FC = () => { + const store = useStore(); + const { selectedFile, setSelectedFile, billType } = useInvoice(); const [showAlertNewFileCreated, setShowAlertNewFileCreated] = useState(false); + const newFile = () => { - if (props.file !== "default") { + if (selectedFile !== "default") { const content = encodeURIComponent(AppGeneral.getSpreadsheetContent()); - const data = props.store._getFile(props.file); + const data = store._getFile(selectedFile); const file = new File( (data as any).created, new Date().toString(), content, - props.file, - props.billType + selectedFile, + billType ); - props.store._saveFile(file); - props.updateSelectedFile(props.file); + store._saveFile(file); + setSelectedFile(selectedFile); } const msc = DATA["home"][AppGeneral.getDeviceType()]["msc"]; AppGeneral.viewFile("default", JSON.stringify(msc)); - props.updateSelectedFile("default"); + setSelectedFile("default"); setShowAlertNewFileCreated(true); }; @@ -41,7 +41,6 @@ const NewFile: React.FC<{ size="large" onClick={() => { newFile(); - // console.log("New file clicked"); }} /> void; + billType: number; + setBillType: (type: number) => void; + showMenu: boolean; + setShowMenu: (show: boolean) => void; +} + +export const InvoiceContext = createContext(null); + +export function useInvoice(): InvoiceContextValue { + const ctx = useContext(InvoiceContext); + if (!ctx) { + throw new Error("useInvoice must be used within an InvoiceProvider"); + } + return ctx; +} diff --git a/src/contexts/StoreContext.tsx b/src/contexts/StoreContext.tsx new file mode 100644 index 0000000..d40d884 --- /dev/null +++ b/src/contexts/StoreContext.tsx @@ -0,0 +1,21 @@ +import { createContext, useContext, useMemo } from "react"; +import { Local } from "../components/Storage/LocalStorage"; + +const StoreContext = createContext(null); + +export function StoreProvider({ children }: { children: React.ReactNode }) { + const store = useMemo(() => new Local(), []); + return ( + + {children} + + ); +} + +export function useStore(): Local { + const store = useContext(StoreContext); + if (!store) { + throw new Error("useStore must be used within a StoreProvider"); + } + return store; +} diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx index 876a058..e4a45f2 100644 --- a/src/pages/Home.tsx +++ b/src/pages/Home.tsx @@ -10,42 +10,31 @@ import { IonTitle, IonToolbar, IonButtons, - IonAlert, - IonToast } from "@ionic/react"; import { APP_NAME, DATA } from "../app-data"; import * as AppGeneral from "../components/socialcalc/index.js"; -import { useEffect, useState } from "react"; -import { Local, File as LocalFile } from "../components/Storage/LocalStorage"; -import { menu, settings, hardwareChipOutline, cloudDownloadOutline, arrowBack } from "ionicons/icons"; +import { useEffect, useState, useCallback, useMemo } from "react"; +import { menu, settings, arrowBack } from "ionicons/icons"; import "./Home.css"; import Menu from "../components/Menu/Menu"; import NewFile from "../components/NewFile/NewFile"; import Dashboard from "../components/Dashboard/Dashboard"; -import { useHistory } from "react-router"; +import { InvoiceContext, InvoiceContextValue } from "../contexts/InvoiceContext"; const Home: React.FC = () => { - const [view, setView] = useState<'dashboard' | 'editor'>('dashboard'); - + const [view, setView] = useState<"dashboard" | "editor">("dashboard"); const [showMenu, setShowMenu] = useState(false); const [showPopover, setShowPopover] = useState<{ open: boolean; event: Event | undefined; }>({ open: false, event: undefined }); - const [selectedFile, updateSelectedFile] = useState("default"); - const [billType, updateBillType] = useState(1); - const [device] = useState("default"); - const history = useHistory(); - - const store = new Local(); - - const closeMenu = () => { - setShowMenu(false); - }; + const [selectedFile, setSelectedFile] = useState("default"); + const [billType, setBillType] = useState(1); + const [device] = useState<"default">("default"); - const activateFooter = (footer) => { + const activateFooter = useCallback((footer: number) => { AppGeneral.activateFooterButton(footer); - }; + }, []); useEffect(() => { const data = DATA["home"][device]["msc"]; @@ -54,7 +43,7 @@ const Home: React.FC = () => { useEffect(() => { activateFooter(billType); - }, [billType]); + }, [billType, activateFooter]); const footers = DATA["home"][device]["footers"]; const footersList = footers.map((footerArray) => { @@ -65,7 +54,7 @@ const Home: React.FC = () => { color="light" className="ion-no-margin" onClick={() => { - updateBillType(footerArray.index); + setBillType(footerArray.index); activateFooter(footerArray.index); setShowPopover({ open: false, event: undefined }); }} @@ -75,99 +64,106 @@ const Home: React.FC = () => { ); }); - return ( - - - - - {view === 'editor' && ( - setView('dashboard')}> - - - )} - - {APP_NAME} - - {view === 'editor' && ( - <> - { - setShowPopover({ open: true, event: e.nativeEvent }); - }} - /> - { updateSelectedFile(f); setView('editor'); }} - store={store} - billType={billType} - /> - > - )} - - setShowPopover({ open: false, event: undefined }) - } - > - {footersList} - - - - - - - {view === 'dashboard' ? ( - { - updateSelectedFile(key); - updateBillType(bT); - setView('editor'); - }} - /> - ) : null} + const invoiceCtx = useMemo( + () => ({ + selectedFile, + setSelectedFile, + billType, + setBillType, + showMenu, + setShowMenu, + }), + [selectedFile, billType, showMenu] + ); - - - - Editing : {selectedFile} - + return ( + + + + + + {view === "editor" && ( + setView("dashboard")}> + + + )} + + {APP_NAME} + + {view === "editor" && ( + <> + { + setShowPopover({ open: true, event: e.nativeEvent }); + }} + /> + + > + )} + + setShowPopover({ open: false, event: undefined }) + } + > + {footersList} + + + + + {view === "dashboard" ? ( + { + setSelectedFile(key); + setBillType(bT); + setView("editor"); + }} + /> + ) : null} - - - - - - + + + + Editing : {selectedFile} + + - {view === 'editor' && ( - - setShowMenu(true)}> - - - - )} + + + + + + - + {view === "editor" && ( + + setShowMenu(true)} + > + + + + )} - - + + + + ); }; diff --git a/src/pages/MeshKit.tsx b/src/pages/MeshKit.tsx index 5640c4f..31725d3 100644 --- a/src/pages/MeshKit.tsx +++ b/src/pages/MeshKit.tsx @@ -40,10 +40,10 @@ import { receiveMessage, revokeCID, } from "../services/MeshkitService"; -import { Local } from "../components/Storage/LocalStorage"; +import { useStore } from "../contexts/StoreContext"; const MeshKitPage: React.FC = () => { - const store = new Local(); + const store = useStore(); const [toastMessage, setToastMessage] = useState(""); const [showToast, setShowToast] = useState(false); diff --git a/src/types/meshkit-ionic.d.ts b/src/types/meshkit-ionic.d.ts new file mode 100644 index 0000000..7f9c6d8 --- /dev/null +++ b/src/types/meshkit-ionic.d.ts @@ -0,0 +1,22 @@ +declare module "@meshkit/ionic" { + export interface MeshkitRecord { + cid: string; + data: T; + } + + export class Meshkit { + static init(options: { + provider: string; + providerToken: string; + }): Promise; + + testConnection(): Promise; + store(data: T): Promise>; + retrieve(cid: string): Promise; + upload(file: Blob): Promise>; + download(cid: string): Promise; + send(recipientId: string, payload: Record): Promise>>; + receive(cid: string): Promise>; + revoke(cid: string): Promise; + } +}
{_formatDate(data.modified)}
No backup history available.
{_formatDate(record.timestamp)}
{record.cid}