This commit is contained in:
zramsay
2025-05-05 16:47:39 -04:00
parent 43e4b38e96
commit f95bde74f7
8 changed files with 348 additions and 36 deletions
+19 -1
View File
@@ -23,7 +23,25 @@ export default function PaymentModal({
// Get recipient address from environment variables
const recipientAddress = process.env.NEXT_PUBLIC_RECIPIENT_ADDRESS || 'cosmos1yourrealaddress';
// Validate amount on change
const handleAmountChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value;
setAmount(value);
// Clear error when user types
if (error) {
setError('');
}
};
const handlePayment = async () => {
// Validate amount before sending
const parsedAmount = parseFloat(amount);
if (isNaN(parsedAmount) || parsedAmount <= 0) {
setError('Please enter a valid positive amount');
return;
}
setLoading(true);
setError('');
@@ -78,7 +96,7 @@ export default function PaymentModal({
min="0.001"
step="0.001"
value={amount}
onChange={(e) => setAmount(e.target.value)}
onChange={handleAmountChange}
className="w-full p-3 pr-12 rounded-md"
style={{
background: 'var(--card-bg)',
+7 -8
View File
@@ -27,6 +27,8 @@ export default function StatusDisplay({
shortCommitHash,
error,
}: StatusDisplayProps) {
// Get domain suffix from environment variable
const domainSuffix = process.env.NEXT_PUBLIC_DOMAIN_SUFFIX || '';
if (status === 'idle') return null;
const StatusBadge = ({ type }: { type: 'verifying' | 'creating' | 'success' | 'error' }) => {
@@ -115,23 +117,20 @@ export default function StatusDisplay({
<h3 className="font-semibold mb-2 text-lg">
Successfully deployed
{appName && <span> {appName}</span>}
{dns && <span> as {dns}</span>}
</h3>
{repoUrl && (
<p className="mb-1 text-sm">
<span className="font-medium">Repository:</span> {repoUrl}
{shortCommitHash && <span> @ {shortCommitHash}</span>}
{(!shortCommitHash && commitHash) && <span> @ {commitHash.substring(0, 7)}</span>}
</p>
)}
</div>
)}
{txHash && <InfoItem label="Transaction Hash" value={txHash} />}
{appRecordId && <InfoItem label="Application Record ID" value={appRecordId} />}
{recordId && <InfoItem label="Deployment Request Record ID" value={recordId} />}
{txHash && <InfoItem label="ATOM Payment Transaction Hash" value={txHash} />}
{appRecordId && <InfoItem label="Laconic Application Record ID" value={appRecordId} />}
{recordId && <InfoItem label="Laconic Deployment Request Record ID" value={recordId} />}
{lrn && <InfoItem label="Laconic Resource Name (LRN)" value={lrn} />}
{dns && <InfoItem label="Deployment DNS" value={dns} />}
{dns && <InfoItem label="Deployment DNS" value={domainSuffix ? `${dns}${domainSuffix}` : dns} />}
</div>
)}
@@ -145,4 +144,4 @@ export default function StatusDisplay({
)}
</div>
);
}
}
+27 -4
View File
@@ -14,18 +14,41 @@ export default function URLForm({ onSubmit, disabled }: URLFormProps) {
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
// Validate URL
// Trim the URL to remove any whitespace
const trimmedUrl = url.trim();
if (!trimmedUrl) {
setError('Please enter a URL');
return;
}
// Validate URL format
try {
const parsedUrl = new URL(url);
const parsedUrl = new URL(trimmedUrl);
// Check for protocol
if (!parsedUrl.protocol.startsWith('http')) {
setError('URL must use HTTP or HTTPS protocol');
return;
}
// Check for hostname
if (!parsedUrl.hostname || parsedUrl.hostname.length < 3) {
setError('URL must contain a valid hostname');
return;
}
// Basic sanity check for common invalid URLs
if (parsedUrl.href === 'http://localhost' || parsedUrl.href === 'https://localhost') {
setError('Please enter a valid public URL, not localhost');
return;
}
// All validations passed
setError('');
onSubmit(url);
onSubmit(trimmedUrl);
} catch (_) {
setError('Please enter a valid URL');
setError('Please enter a valid URL (e.g., https://example.com)');
}
};