diff --git a/QuickStartTemplate/projects/QuickStartTemplate-contracts/nft_mint_server/app.js b/QuickStartTemplate/projects/QuickStartTemplate-contracts/nft_mint_server/app.js index 5c734c0..a38ee75 100644 --- a/QuickStartTemplate/projects/QuickStartTemplate-contracts/nft_mint_server/app.js +++ b/QuickStartTemplate/projects/QuickStartTemplate-contracts/nft_mint_server/app.js @@ -1,11 +1,11 @@ // Shared Express app (no .listen here) -import express from 'express' -import cors from 'cors' -import multer from 'multer' import pinataSDK from '@pinata/sdk' +import cors from 'cors' import dotenv from 'dotenv' -import { Readable } from 'stream' +import express from 'express' +import multer from 'multer' import path from 'path' +import { Readable } from 'stream' import { fileURLToPath } from 'url' const __filename = fileURLToPath(import.meta.url) @@ -46,6 +46,12 @@ const pinata = process.env.PINATA_JWT // Optional: test credentials at cold start ;(async () => { + const skip = process.env.SKIP_PINATA_TEST === 'true' || !process.env.PINATA_API_KEY || process.env.PINATA_API_KEY.includes('YOUR_PINATA') + if (skip) { + console.log('Pinata auth test skipped (set SKIP_PINATA_TEST=false and provide real keys to enable).') + return + } + try { const auth = await pinata.testAuthentication?.() console.log('Pinata auth OK:', auth || 'ok') diff --git a/QuickStartTemplate/projects/QuickStartTemplate-contracts/package.json b/QuickStartTemplate/projects/QuickStartTemplate-contracts/package.json index 728978a..522f6b5 100644 --- a/QuickStartTemplate/projects/QuickStartTemplate-contracts/package.json +++ b/QuickStartTemplate/projects/QuickStartTemplate-contracts/package.json @@ -5,6 +5,7 @@ "main": "smart_contracts/index.ts", "type": "module", "scripts": { + "dev": "node nft_mint_server/server.js", "build": "algokit compile ts smart_contracts --output-source-map --out-dir artifacts && algokit generate client smart_contracts/artifacts --output {app_spec_dir}/{contract_name}Client.ts", "deploy": "ts-node-dev --transpile-only --watch .env -r dotenv/config smart_contracts/index.ts", "deploy:ci": "ts-node --transpile-only -r dotenv/config smart_contracts/index.ts", diff --git a/QuickStartTemplate/projects/QuickStartTemplate-frontend/src/App.tsx b/QuickStartTemplate/projects/QuickStartTemplate-frontend/src/App.tsx index 9792c8d..7543341 100644 --- a/QuickStartTemplate/projects/QuickStartTemplate-frontend/src/App.tsx +++ b/QuickStartTemplate/projects/QuickStartTemplate-frontend/src/App.tsx @@ -1,8 +1,17 @@ import { SupportedWallet, WalletId, WalletManager, WalletProvider } from '@txnlab/use-wallet-react' +import { Analytics } from '@vercel/analytics/react' import { SnackbarProvider } from 'notistack' import Home from './Home' import { getAlgodConfigFromViteEnvironment, getKmdConfigFromViteEnvironment } from './utils/network/getAlgoClientConfigs' -import { Analytics } from '@vercel/analytics/react' + +import React, { useState } from 'react' +// ServicesPage replaced by rendering `Home` directly so users see service links on the homepage +import HelpPage from './pages/HelpPage' +import RegisterVehicle from './pages/RegisterVehicle' +import Settings from './pages/Settings' +import TransferTitle from './pages/TransferTitle' + +// ...existing code... let supportedWallets: SupportedWallet[] if (import.meta.env.VITE_ALGOD_NETWORK === 'localnet') { @@ -32,6 +41,19 @@ if (import.meta.env.VITE_ALGOD_NETWORK === 'localnet') { export default function App() { const algodConfig = getAlgodConfigFromViteEnvironment() + const [stage, setStage] = useState<'auth' | 'congrats' | 'app'>('auth') + const [authPage, setAuthPage] = useState<'signin' | 'signup'>('signin') + const [formUserId, setFormUserId] = useState('') + const [formPassphrase, setFormPassphrase] = useState('') + const [formConfirmPassphrase, setFormConfirmPassphrase] = useState('') + + // app view state inside authenticated 'app' stage (declare hooks unconditionally) + const [appView, setAppView] = useState<'services' | 'register' | 'transfer' | 'help' | 'settings'>('services') + + // Authenticated user info to show on congrats page + const [authUser, setAuthUser] = useState(null) + const [authInternalId, setAuthInternalId] = useState(null) + const walletManager = new WalletManager({ wallets: supportedWallets, defaultNetwork: algodConfig.network, @@ -49,12 +71,132 @@ export default function App() { }, }) - return ( - - - - - - - ) + // Render sign-in / sign-up before showing the wallet UI + if (stage === 'auth') { + const handleSignIn = (e: React.FormEvent) => { + e.preventDefault() + // basic validation placeholder + if (!formUserId || !formPassphrase) return + // set authenticated user info and move to congratulations screen + setAuthUser(formUserId) + setAuthInternalId(Date.now().toString(36)) + setStage('congrats') + } + + const handleSignUp = (e: React.FormEvent) => { + e.preventDefault() + // basic validation placeholder + if (!formUserId || !formPassphrase || !formConfirmPassphrase) return + if (formPassphrase !== formConfirmPassphrase) return + // set authenticated user info and move to congratulations screen + setAuthUser(formUserId) + setAuthInternalId(Date.now().toString(36)) + setStage('congrats') + } + + return ( +
+
+

+ {authPage === 'signin' ? 'Sign In' : 'Sign Up'} +

+ {authPage === 'signin' ? ( +
+
+ + setFormUserId(e.target.value)} className="w-full border rounded px-3 py-2" placeholder="Enter your User ID" /> +
+
+ + setFormPassphrase(e.target.value)} className="w-full border rounded px-3 py-2" placeholder="Enter your passphrase" /> +
+ +
+ ) : ( +
+
+ + setFormUserId(e.target.value)} className="w-full border rounded px-3 py-2" placeholder="Enter your User ID" /> +
+
+ + setFormPassphrase(e.target.value)} className="w-full border rounded px-3 py-2" placeholder="Enter your passphrase" /> +
+
+ + setFormConfirmPassphrase(e.target.value)} className="w-full border rounded px-3 py-2" placeholder="Confirm your passphrase" /> +
+ +
+ )} + +
+ {authPage === 'signin' ? ( + + ) : ( + + )} +
+
+
+ ) + } + + // Congratulations page shown after successful sign in / sign up + if (stage === 'congrats') { + return ( +
+
+

Congratulations!

+ {authUser && authInternalId ? ( +
+

Welcome, {authUser}!

+

Your ID: {authInternalId}

+
+ ) : ( +

Your account is ready.

+ )} +

Click the button below to continue to the app.

+ +
+
+ ) + } + + if (stage === 'app') { + const goBackToServices = () => setAppView('services') + + return ( + + +
+
+

QuickStart Template

+
+ +
+
+ +
+ {appView === 'services' && setAppView(v)} />} + {appView === 'register' && } + {appView === 'transfer' && } + {appView === 'help' && } + {appView === 'settings' && } +
+ + +
+
+
+ ) + } + + // Fallback (shouldn't be reachable because `stage` is restricted) + return null } diff --git a/QuickStartTemplate/projects/QuickStartTemplate-frontend/src/Home.tsx b/QuickStartTemplate/projects/QuickStartTemplate-frontend/src/Home.tsx index 461a9b6..82c10ef 100644 --- a/QuickStartTemplate/projects/QuickStartTemplate-frontend/src/Home.tsx +++ b/QuickStartTemplate/projects/QuickStartTemplate-frontend/src/Home.tsx @@ -1,4 +1,4 @@ -// Home.tsx - Professional Clean Light UI +// Home.tsx - Dark UI (Black & Grey Background, White Headings) import { useWallet } from '@txnlab/use-wallet-react' import React, { useState } from 'react' @@ -12,12 +12,15 @@ import NFTmint from './components/NFTmint' import Tokenmint from './components/Tokenmint' import Transact from './components/Transact' -interface HomeProps {} +interface HomeProps { + onNavigate?: (view: 'services' | 'register' | 'transfer' | 'help' | 'settings') => void +} -const cardBase = 'rounded-xl shadow-md hover:shadow-lg transition border border-gray-200 bg-white' -const iconStyle = 'text-3xl text-gray-700' +// Updated card styling for dark theme +const cardBase = 'rounded-xl shadow-md hover:shadow-lg transition border border-gray-700 bg-gray-900' +const iconStyle = 'text-3xl text-gray-200' -const Home: React.FC = () => { +const Home: React.FC = ({ onNavigate }) => { const [openWalletModal, setOpenWalletModal] = useState(false) const [openPaymentModal, setOpenPaymentModal] = useState(false) const [openMintModal, setOpenMintModal] = useState(false) @@ -27,118 +30,165 @@ const Home: React.FC = () => { const { activeAddress } = useWallet() return ( -
+
+ {/* Navbar */} - - {/* Features */} -
- {activeAddress ? ( -
-

Available Actions

- -
- + + +
+
+ +
+
+
+
+
Account
+
{activeAddress ? activeAddress : 'Not connected'}
+
+
+ +
+
+
Balance
+
— ALGO
+
+ +
+
Network
+
+
+
+
+
+
+
+ + +
+
+
+

Available Actions

+
+ + - - - +
-
- ) : ( -
-

Connect your wallet to access all actions.

-
- )} + + + +
- {/* Footer */} -