From 5efa3d3270d11fa67a7fdc2e000d255953c85c8c Mon Sep 17 00:00:00 2001 From: Suvodip Date: Fri, 11 Apr 2025 12:59:43 +0530 Subject: [PATCH] s12 --- package-lock.json | 49 ++ package.json | 1 + src/components/DomainSetupForm.jsx | 696 ++++++++++++++++------------- src/components/Login.tsx | 8 +- src/components/MakePayment.jsx | 180 ++++++++ src/components/PaymentForm.jsx | 0 src/components/TestCool.jsx | 171 +++++++ src/components/Ticket.tsx | 3 +- src/components/Topic.tsx | 26 ++ src/components/UserProfile.tsx | 37 +- src/pages/make-payment.astro | 9 + src/pages/payment.astro | 9 + src/pages/test-cool.astro | 7 + src/pages/topic.astro | 7 + yarn.lock | 40 +- 15 files changed, 915 insertions(+), 328 deletions(-) create mode 100644 src/components/MakePayment.jsx create mode 100644 src/components/PaymentForm.jsx create mode 100644 src/components/TestCool.jsx create mode 100644 src/components/Topic.tsx create mode 100644 src/pages/make-payment.astro create mode 100644 src/pages/payment.astro create mode 100644 src/pages/test-cool.astro create mode 100644 src/pages/topic.astro diff --git a/package-lock.json b/package-lock.json index 296aba7..6ae6710 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,6 +25,7 @@ "lucide-react": "^0.484.0", "pocketbase": "^0.25.2", "postcss": "^8.5.3", + "react-qr-code": "^2.0.15", "react-router-dom": "^7.4.1", "react-to-print": "^3.0.5", "tailwind-merge": "^3.0.2", @@ -4524,6 +4525,18 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, "node_modules/lru-cache": { "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", @@ -6009,6 +6022,17 @@ "node": ">=6" } }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, "node_modules/property-information": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.0.0.tgz", @@ -6019,6 +6043,12 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/qr.js": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/qr.js/-/qr.js-0.0.0.tgz", + "integrity": "sha512-c4iYnWb+k2E+vYpRimHqSu575b1/wKl4XFeJGpFmrJQz5I88v9aY2czh7s0w36srfCM1sXgC/xpoJz5dJfq+OQ==", + "license": "MIT" + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -6068,6 +6098,25 @@ "react": "^19.0.0" } }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" + }, + "node_modules/react-qr-code": { + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/react-qr-code/-/react-qr-code-2.0.15.tgz", + "integrity": "sha512-MkZcjEXqVKqXEIMVE0mbcGgDpkfSdd8zhuzXEl9QzYeNcw8Hq2oVIzDLWuZN2PQBwM5PWjc2S31K8Q1UbcFMfw==", + "license": "MIT", + "dependencies": { + "prop-types": "^15.8.1", + "qr.js": "0.0.0" + }, + "peerDependencies": { + "react": "*" + } + }, "node_modules/react-refresh": { "version": "0.14.2", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", diff --git a/package.json b/package.json index 6c1da60..5a5fe36 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "lucide-react": "^0.484.0", "pocketbase": "^0.25.2", "postcss": "^8.5.3", + "react-qr-code": "^2.0.15", "react-router-dom": "^7.4.1", "react-to-print": "^3.0.5", "tailwind-merge": "^3.0.2", diff --git a/src/components/DomainSetupForm.jsx b/src/components/DomainSetupForm.jsx index 4f448f1..adbd070 100644 --- a/src/components/DomainSetupForm.jsx +++ b/src/components/DomainSetupForm.jsx @@ -1,7 +1,9 @@ import React, { useState, useEffect } from 'react'; import { Toast } from './Toast'; import { TemplatePreview } from './TemplatePreview'; - +import { Button } from './ui/button'; +import { Input } from "./ui/input"; +import { Label, Select } from '@radix-ui/react-select'; export const DomainSetupForm = ({ defaultSubdomain }) => { // Deployment type and app selections const [deploymentType, setDeploymentType] = useState('app'); @@ -27,12 +29,73 @@ export const DomainSetupForm = ({ defaultSubdomain }) => { // DNS configuration const [dnsMethod, setDnsMethod] = useState('cname'); const [showDnsConfig, setShowDnsConfig] = useState(false); - const [dnsVerified, setDnsVerified] = useState({ - cname: false, - ns: false, - a: false, - ip: false - }); + const [dnsVerified, setDnsVerified] = useState({ cname: false, ns: false, a: false, ip: false}); + const [txnId, setTxnId] = useState(''); + const [userEmail, setUserEmail] = useState(''); + + const [panelType, setPanelType] = useState(''); + const API_URL = 'http://192.168.1.197:2058/v1/users/index.php'; + const SERVICES_API_URL = 'http://192.168.1.197:2058/v1/services/index.php'; + // const BILLING_API_URL = 'http://192.168.1.197:2058/v1/users/index.php'; + + const [selectedTenure, setSelectedTenure] = useState(''); + const [selectedPrice, setSelectedPrice] = useState(0); + + const handleCheckboxChange = (tenure, price) => { + if (selectedTenure === tenure) { + setSelectedTenure(''); + setSelectedPrice(0); + } else { + setSelectedTenure(tenure); + setSelectedPrice(price); + } + // console.log(selectedTenure, ' ', selectedPrice); + }; + const handlePanelBuyNow = () => { + // Disable button during processing + const buyButton = document.getElementById('buy-button'); // Add ID to your button + if (buyButton) buyButton.disabled = true; + + showToast('Loading...'); + const formData = new FormData(); + formData.append('service', panelType); + formData.append('tenure', selectedTenure); + formData.append('amount', 1); //selectedPrice + + fetch(`${API_URL}?query=initiate_payment`, { + method: 'POST', + body: formData, + credentials: 'include' + }) + .then(response => { + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + return response.json(); + }) + .then(data => { + if(data.success === true){ + setTxnId(data.txn_id); + setUserEmail(data.user_email); + window.location.href = `/make-payment?query=get-initiated_payment&orderId=${data.order_id}` + // redirectToPayU(data); + showToast('Redirecting to payment page...'); + } else { + throw new Error(data.message || 'Payment initialization failed'); + } + }) + .catch(error => { + showToast(error.message || 'Payment failed. Please try again.'); + console.error('An error occurred:', error); + }) + .finally(() => { + if (buyButton) buyButton.disabled = false; + }); + }; + + + + // Form validation const [formValid, setFormValid] = useState(true); @@ -159,52 +222,71 @@ export const DomainSetupForm = ({ defaultSubdomain }) => { }; // Validate domain - const validateDomain = () => { + const validateDomain = async () => { const domain = domainType === 'domain' ? customDomain : customSubdomain; - - if (!domain) { - setValidationMessage('Please enter a domain name.'); - setIsValidDomain(false); - return; - } - - // Initial validation: check format with regex - const validFormat = /^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$/.test(domain); - if (!validFormat) { - setValidationMessage('Domain format is invalid. Please check your entry.'); - setIsValidDomain(false); - return; - } - + + // Reset validation state setIsValidating(true); + setIsValidDomain(false); setValidationMessage(''); setShowDnsConfig(false); - - // Simulate an API call to validate the domain - setTimeout(() => { - // Simulate a real domain check - in a real app this would be an API call - // call /host-api/v1/domains/validate/?domain=domain.com - const checkResult = true; // Assume domain is valid for demo - + + // Check if domain is empty + if (!domain) { + setValidationMessage('Please enter a domain name.'); setIsValidating(false); - setIsValidDomain(checkResult); - - if (checkResult) { + setIsValidDomain(false); + return; + } + + // Validate domain format + const domainFormatRegex = /^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,}$/i; + if (!domainFormatRegex.test(domain)) { + setValidationMessage('Domain format is invalid. Please check your entry.'); + setIsValidating(false); + setIsValidDomain(false); + return; + } + + try { + // Make API call to validate domain + const response = await fetch(`${SERVICES_API_URL}?query=validate-domain`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ domain }) + }); + + if (!response.ok) { + throw new Error('Network response was not ok'); + } + + const data = await response.json(); + + if (data.valid) { setValidationMessage('Domain is valid and registered.'); + setIsValidDomain(true); setShowDnsConfig(true); } else { - setValidationMessage('Domain appears to be unregistered or unavailable.'); + setValidationMessage(data.message || 'Domain appears to be unregistered or unavailable.'); + setIsValidDomain(false); } - + } catch (error) { + console.error('Domain validation error:', error); + setValidationMessage('Error validating domain. Please try again.'); + setIsValidDomain(false); + } finally { + setIsValidating(false); validateForm(); - }, 500); + } }; // Check DNS configuration const checkSubDomainCname = () => { const domainToCheck = customDomain || customSubdomain; - fetch('http://localhost:2058/host-api/v1/check-c-name/', { + fetch(`${SERVICES_API_URL}?query=check-c-name`, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', @@ -312,6 +394,7 @@ export const DomainSetupForm = ({ defaultSubdomain }) => { + @@ -461,316 +544,321 @@ export const DomainSetupForm = ({ defaultSubdomain }) => { )} + { + deploymentType === 'php-mysql-with-admin-panel' && ( +
+ + +
+ ) + + } + { + deploymentType === 'php-mysql-with-admin-panel' && panelType === 'Hestia-Panel' && ( + <> + +
+ - {/* Domain Configuration */} -
-

Destination

- -
- {/* SiliconPin Subdomain */} -
- -
- -
- - .subdomain.siliconpin.com -
-
+
+
+ {selectedTenure && ( +

You selected {selectedTenure} plan at ₹{selectedPrice}

+ )} +
+ + ) + } + { + deploymentType === 'php-mysql-with-admin-panel' && panelType === 'cPanel' ? ( +
+

+ cPanel is a proprietary software. Here at Siliconpin, we encourage using freedom-oriented software. + If you need a cPanel, you can visit   + https://cicdhosting.com +

+
- {/* Custom Domain */} -
- -
- + ) : deploymentType === 'php-mysql-with-admin-panel' && ( + + ) + } + { + deploymentType !== 'php-mysql-with-admin-panel' && ( + <> + {/* Domain Configuration */} +
+

Destination

- {useCustomDomain && ( -
- {/* Domain Type Selection */} -
-
- - -
- -
- - -
+
+ {/* SiliconPin Subdomain */} +
+ +
+ +
+ + .subdomain.siliconpin.com
+
+
- {/* Domain Input */} - {domainType === 'domain' ? ( -
- -

- Enter domain without http://, www, or trailing slashes (example.com). You can configure www or other subdomains later. -

-
- ) : ( -
- -

- Enter the full subdomain without http:// or trailing slashes. www and protocol prefixes will be automatically removed. -

-
- )} + {/* Custom Domain */} +
+ +
+ - {/* Domain Validation */} - + {useCustomDomain && ( +
+ {/* Domain Type Selection */} +
+
+ + +
- {/* Validation Status */} - {useCustomDomain && isValidating && ( -
-
-
-

Verifying domain registration and availability...

+
+ + +
-
- )} - {useCustomDomain && !isValidating && validationMessage && ( -
-

- {validationMessage} -

-
- )} - - {/* DNS Configuration Options */} - {showDnsConfig && ( -
-

Connect Your Domain

- - {/* CNAME Record Option */} -
-
-
- {/* Form Submit Button */} - + {/* Form Submit Button */} + + + ) + }
); }; +// upi://pay?pa=merchant@bank&pn=Merchant%20Inc&am=100.00&cu=INR&tn=Payment%20for%20goods + + diff --git a/src/components/Login.tsx b/src/components/Login.tsx index 0426fb6..b38f04b 100644 --- a/src/components/Login.tsx +++ b/src/components/Login.tsx @@ -28,8 +28,8 @@ interface AuthResponse { const LoginPage = () => { - const [email, setEmail] = useState('suvodip@siliconpin.com'); - const [password, setPassword] = useState('Simple2pass'); + const [email, setEmail] = useState(''); + const [password, setPassword] = useState(''); const [passwordVisible, setPasswordVisible] = useState(false); const [status, setStatus] = useState({ message: '', isError: false }); const [isLoading, setIsLoading] = useState(false); @@ -115,10 +115,10 @@ const LoginPage = () => { setIsLoading(false); } }; - + const syncSessionWithBackend = async (authData: AuthResponse, avatarUrl: string) => { try { - const response = await fetch('http://localhost:2058/host-api/v1/users/session/', { + const response = await fetch('http://192.168.1.197:2058/v1/users/?query=login', { method: 'POST', credentials: 'include', // Important for cookies headers: { 'Content-Type': 'application/json' }, diff --git a/src/components/MakePayment.jsx b/src/components/MakePayment.jsx new file mode 100644 index 0000000..47be175 --- /dev/null +++ b/src/components/MakePayment.jsx @@ -0,0 +1,180 @@ +import React, {useState, useEffect} from "react"; +import { Button } from "./ui/button"; +import QRCode from "react-qr-code"; +import { Dialog, DialogContent, DialogHeader, DialogTitle} from "./ui/dialog"; +import { Toast } from './Toast'; +import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "./ui/card"; + +const API_URL = 'http://192.168.1.197:2058/v1/users/index.php'; + +export default function MakePayment(){ + const [initialOrderData, setInitialOrderData] = useState(null); + const [isLoading, setIsLoading] = useState(true); + const [error, setError] = useState(null); + const [showQRModal, setShowQRModal] = useState(false); + const [upiPaymentLink, setUpiPaymentLink] = useState(""); + + useEffect(() => { + const urlParams = new URLSearchParams(window.location.search); + const orderId = urlParams.get('orderId'); + + if (!orderId) { + setError('Order ID is missing from URL'); + setIsLoading(false); + return; + } + + const getInitialOrderData = () => { + setIsLoading(true); + const formData = new FormData(); + formData.append('order_id', orderId); + + fetch(`${API_URL}?query=get-initiated_payment`, { + method: 'POST', + body: formData, + credentials: 'include' + }) + .then(response => { + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + return response.json(); + }) + .then(data => { + if (!data.success) { + throw new Error(data.message || 'Failed to initialize payment'); + } + setInitialOrderData(data); + setError(null); + + // Generate UPI payment link when data is loaded + if (data.payment_data?.amount) { + const amount = data.payment_data.amount; + const upiLink = generateUPILink(amount, data.txn_id); + setUpiPaymentLink(upiLink); + } + }) + .catch(error => { + setError(error.message || 'Payment failed. Please try again.'); + console.error('An error occurred:', error); + }) + .finally(() => { + setIsLoading(false); + }); + }; + + getInitialOrderData(); + }, []); + + function generateUPILink(amount, transactionId) { + // Replace these with your actual merchant details + const merchantUPI = "siliconpin@ybl"; + const merchantName = "SiliconPin"; + const currency = "INR"; + + // Encode parameters for URL + const encodedMerchantName = encodeURIComponent(merchantName); + const transactionNote = encodeURIComponent(`Payment for order #${transactionId}`); + + // Construct UPI payment link + return `upi://pay?pa=${merchantUPI}&pn=${encodedMerchantName}&am=${amount}&cu=${currency}&tn=${transactionNote}`; + } +// waiting payment update +// Payment update not recieved if + function redirectToPayU() { + if (!initialOrderData?.payment_data || !initialOrderData.payment_url) { + console.error('Payment data not loaded yet'); + alert('Payment information is not ready. Please wait.'); + return; + } + + // Create a form dynamically + const form = document.createElement('form'); + form.method = 'POST'; + form.action = initialOrderData.payment_url; + form.style.display = 'none'; + + Object.entries(initialOrderData.payment_data).forEach(([key, value]) => { + const input = document.createElement('input'); + input.type = 'hidden'; + input.name = key; + input.value = value; + form.appendChild(input); + }); + + document.body.appendChild(form); + form.submit(); + } + + function handleQRPaymentClick() { + if (!upiPaymentLink) { + alert('Payment information is not ready. Please wait.'); + return; + } + setShowQRModal(true); + } + + if (isLoading) { + return
+
+
; + } + + if (error) { + return
+
+ Error: {error} +
+
; + } + + return ( +
+ +

Complete Your Payment

+ + {initialOrderData && ( +
+
+ Order ID: + {initialOrderData.txn_id} +
+
+ Amount: + ₹{initialOrderData.payment_data?.amount} +
+
+ )} + +
+ Pay Using: + + OR + + Applicabel 2% Transaction Charge if using Payment Gateway +
+
+ + {/* QR Code Modal */} + + + + Scan QR Code to Pay + +
+
+ +
+

+ Scan this QR code with any UPI app to complete your payment +

+
+ {upiPaymentLink} +
+ +
+
+
+
+ ); +} \ No newline at end of file diff --git a/src/components/PaymentForm.jsx b/src/components/PaymentForm.jsx new file mode 100644 index 0000000..e69de29 diff --git a/src/components/TestCool.jsx b/src/components/TestCool.jsx new file mode 100644 index 0000000..23447c9 --- /dev/null +++ b/src/components/TestCool.jsx @@ -0,0 +1,171 @@ +import React, { useState } from "react"; + +export default function DeployWordPress() { + const [loading, setLoading] = useState(false); + const [message, setMessage] = useState(""); + const [debugInfo, setDebugInfo] = useState(null); + + // Configuration - Replace with your actual values + const COOLIFY_API_URL = "http://192.168.1.197:8000/api/v1"; + const TOKEN = "zXSR33z74eK26abbKyL9bz4d3PYouTSK8FSjOltv719c52d8"; + const PROJECT_UUID = "wc40gg048gkwg0go80ggog44"; + const SERVER_UUID = "sgswssowscc84o8sc8wockgc"; + const ENVIRONMENT_NAME = "production"; // Changed from 'dev' to 'production' as default + + const createWordPress = async () => { + setLoading(true); + setMessage(""); + setDebugInfo(null); + + try { + // 1. Create MySQL Service - Updated to Coolify's expected format + const mysqlPayload = { + name: "wordpress-db", + type: "mysql", + projectUuid: PROJECT_UUID, + serverUuid: SERVER_UUID, + version: "8.0", + destination: { // Coolify often requires this structure + serverUuid: SERVER_UUID, + environment: ENVIRONMENT_NAME + }, + configuration: { + type: "mysql", + settings: { // Changed from environmentVariables to settings + MYSQL_ROOT_PASSWORD: "example", + MYSQL_DATABASE: "wordpress", + MYSQL_USER: "wordpress", + MYSQL_PASSWORD: "example", + MYSQL_ALLOW_EMPTY_PASSWORD: "no" + } + } + }; + + const mysqlRes = await fetch(`${COOLIFY_API_URL}/services`, { + method: "POST", + headers: { + Authorization: `Bearer ${TOKEN}`, + "Content-Type": "application/json", + }, + body: JSON.stringify(mysqlPayload), + }); + + const mysqlData = await mysqlRes.json(); + setDebugInfo({ mysql: { request: mysqlPayload, response: mysqlData } }); + + if (!mysqlRes.ok) { + throw new Error( + mysqlData.message || + mysqlData.error?.message || + JSON.stringify(mysqlData.errors) || + "MySQL validation failed" + ); + } + + // 2. Create WordPress Service + const wpPayload = { + name: "wordpress", + type: "wordpress", + projectUuid: PROJECT_UUID, + serverUuid: SERVER_UUID, + version: "latest", + destination: { + serverUuid: SERVER_UUID, + environment: ENVIRONMENT_NAME + }, + configuration: { + type: "wordpress", + settings: { + WORDPRESS_DB_HOST: "wordpress-db", + WORDPRESS_DB_USER: "wordpress", + WORDPRESS_DB_PASSWORD: "example", + WORDPRESS_DB_NAME: "wordpress", + WORDPRESS_TABLE_PREFIX: "wp_" + } + } + }; + + const wpRes = await fetch(`${COOLIFY_API_URL}/services`, { + method: "POST", + headers: { + Authorization: `Bearer ${TOKEN}`, + "Content-Type": "application/json", + }, + body: JSON.stringify(wpPayload), + }); + + const wpData = await wpRes.json(); + setDebugInfo(prev => ({ ...prev, wordpress: { request: wpPayload, response: wpData } })); + + if (!wpRes.ok) { + throw new Error( + wpData.message || + wpData.error?.message || + JSON.stringify(wpData.errors) || + "WordPress validation failed" + ); + } + + setMessage("🎉 WordPress + MySQL deployed successfully!"); + } catch (err) { + setMessage(`❌ Deployment failed: ${err.message}`); + console.error("Deployment error:", err, debugInfo); + } finally { + setLoading(false); + } + }; + + return ( +
+

Deploy WordPress

+ + + + {message && ( +
+ {message} +
+ )} + + {debugInfo && ( +
+
+ Debug Details +
+
{JSON.stringify(debugInfo, null, 2)}
+
+
+
+

Troubleshooting:

+
    +
  • Verify PROJECT_UUID and SERVER_UUID are correct
  • +
  • Check if environment {ENVIRONMENT_NAME} exists
  • +
  • Ensure your Coolify version supports this API format
  • +
+
+
+ )} +
+ ); +} + + +// [{"uuid":"sgswssowscc84o8sc8wockgc","description":"This is the server where Coolify is running on. Don't delete this!","name":"localhost","ip":"host.docker.internal","is_coolify_host":true,"is_reachable":true,"is_usable":true,"port":22,"proxy":{"redirect_enabled":true},"settings":{"id":1,"concurrent_builds":2,"delete_unused_networks":false,"delete_unused_volumes":false,"docker_cleanup_frequency":"0 0 * * *","docker_cleanup_threshold":80,"dynamic_timeout":3600,"force_disabled":false,"force_docker_cleanup":true,"generate_exact_labels":false,"is_build_server":false,"is_cloudflare_tunnel":false,"is_jump_server":false,"is_logdrain_axiom_enabled":false,"is_logdrain_custom_enabled":false,"is_logdrain_highlight_enabled":false,"is_logdrain_newrelic_enabled":false,"is_metrics_enabled":false,"is_reachable":true,"is_sentinel_debug_enabled":false,"is_sentinel_enabled":false,"is_swarm_manager":false,"is_swarm_worker":false,"is_usable":true,"logdrain_axiom_api_key":null,"logdrain_axiom_dataset_name":null,"logdrain_custom_config":null,"logdrain_custom_config_parser":null,"logdrain_highlight_project_id":null,"logdrain_newrelic_base_uri":null,"logdrain_newrelic_license_key":null,"sentinel_custom_url":"http:\/\/host.docker.internal:8000","sentinel_metrics_history_days":7,"sentinel_metrics_refresh_rate_seconds":10,"sentinel_push_interval_seconds":60,"sentinel_token":"eyJpdiI6IllwMlBsOUtXODdUR0ZIbWtZenJRWFE9PSIsInZhbHVlIjoiZFUxcE9zSXFXdkVrN0tDUGdSbHpGVTE3cHVEeFlBM1hFWk56S05NVWVmVmxHV0tBQ2kra25uRnVzRzNHaFpBSGVTaGZLMGpqdS9nMU85MXhmS3VYMVE9PSIsIm1hYyI6ImY3ODQyNGI2OTVlMmRiMzFmNzJjZjRlYjNkNDIxOGVmZTAxOWMyNjY0ZTYxODE5MDIwY2FhMGUwYjU4ODMyN2MiLCJ0YWciOiIifQ==","server_disk_usage_check_frequency":"0 23 * * *","server_disk_usage_notification_threshold":80,"server_id":0,"server_timezone":"UTC","wildcard_domain":null,"created_at":"2025-04-03T17:12:45.000000Z","updated_at":"2025-04-03T17:16:25.000000Z"},"user":"root"}] \ No newline at end of file diff --git a/src/components/Ticket.tsx b/src/components/Ticket.tsx index eb8d666..a05b03b 100644 --- a/src/components/Ticket.tsx +++ b/src/components/Ticket.tsx @@ -1,6 +1,5 @@ import React, { useState, useEffect } from "react"; import { Button } from "./ui/button"; -import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "./ui/card"; import Table from "./ui/table"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from "./ui/dialog"; import { Input } from "./ui/input"; @@ -28,7 +27,7 @@ interface Message { user_type: string; } -const API_URL = 'http://localhost:2058/host-api/app/v1/ticket/index.php'; +const API_URL = 'http://192.168.1.197:2058/v1/ticket/index.php'; function Ticketing() { const [tickets, setTickets] = useState([]); diff --git a/src/components/Topic.tsx b/src/components/Topic.tsx new file mode 100644 index 0000000..72364b0 --- /dev/null +++ b/src/components/Topic.tsx @@ -0,0 +1,26 @@ +import React, {useEffect, useState} from "react"; +import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "./ui/card"; + +export default function TopicCreation(){ + const API_URL = 'http://192.168.1.197:2058/v1/users/index.php'; + // useEffect(() => { + // fetch(`${API_URL}?query=get-topic`) + // .then(response => response.json()) + // .then{(data: any) => { + // console.log(data); + // }} + // }) + return( + <> +
+
+ + + Lorem ipsum dolor sit amet consectetur adipisicing elit. Quo, excepturi ipsum et animi debitis doloremque quam aliquid quaerat. Totam officiis iste laudantium amet corrupti, doloribus sunt minima dolor odit. Ipsum. + + +
+
+ + ) +} diff --git a/src/components/UserProfile.tsx b/src/components/UserProfile.tsx index ec1d211..1bed53b 100644 --- a/src/components/UserProfile.tsx +++ b/src/components/UserProfile.tsx @@ -8,6 +8,7 @@ import { Separator } from "./ui/separator"; import { Textarea } from "./ui/textarea"; import React, { useState, useEffect } from 'react'; import UpdateAvatar from './UpdateAvatar'; +import {localizeTime} from "../lib/localizeTime"; interface SessionData { [key: string]: any; @@ -24,13 +25,12 @@ export default function ProfilePage() { const [userData, setUserData] = useState(null); const [invoiceList, setInvoiceList] = useState([]); const [error, setError] = useState(null); - + const USER_API_URL = 'http://192.168.1.197:2058/v1/users/index.php'; + const INVOICE_API_URL = 'http://192.168.1.197:2058/v1/invoice/'; useEffect(() => { const fetchSessionData = async () => { try { - const response = await fetch( - 'http://localhost:2058/host-api/v1/users/get-profile-data/', - { + const response = await fetch(`${USER_API_URL}?query=get-user`, { credentials: 'include', // Crucial for cookies headers: { 'Accept': 'application/json' } } @@ -49,7 +49,7 @@ export default function ProfilePage() { }; const getInvoiceListData = async () => { try { - const response = await fetch('http://localhost:2058/host-api/v1/invoice/invoice-info/', { + const response = await fetch(`${USER_API_URL}?query=invoice-info`, { method: 'GET', credentials: 'include', // Crucial for cookies headers: { 'Accept': 'application/json' } @@ -105,7 +105,6 @@ export default function ProfilePage() { JP -
@@ -128,17 +127,22 @@ export default function ProfilePage() { - Billing Information +
+ Billing Information + View All +
+ View your billing history. - - + + + @@ -146,16 +150,19 @@ export default function ProfilePage() { { invoiceList.map((invoice) => ( - - - - - + + + + + + )) } -
Invoice IDDateInvoiceInvoice Date Description AmountStatus Action
{invoice.invoice_id}{invoice.date}{invoice.description}{invoice.amount}Print{invoice.invoice_number}{invoice.invoice_date}{invoice.notes ? invoice.notes : ''}{invoice.total_amount}{invoice.status} + View +
+
diff --git a/src/pages/make-payment.astro b/src/pages/make-payment.astro new file mode 100644 index 0000000..d71591d --- /dev/null +++ b/src/pages/make-payment.astro @@ -0,0 +1,9 @@ +--- +import Layout from "../layouts/Layout.astro"; +import MakePaymentPage from "../components/MakePayment"; +--- + +
+ +
+
\ No newline at end of file diff --git a/src/pages/payment.astro b/src/pages/payment.astro new file mode 100644 index 0000000..2900b47 --- /dev/null +++ b/src/pages/payment.astro @@ -0,0 +1,9 @@ +--- +import Layout from "../layouts/Layout.astro"; +--- + +
+

Payment Page

+

We are working on this!

+
+
\ No newline at end of file diff --git a/src/pages/test-cool.astro b/src/pages/test-cool.astro new file mode 100644 index 0000000..422a075 --- /dev/null +++ b/src/pages/test-cool.astro @@ -0,0 +1,7 @@ +--- +import Layout from "../layouts/Layout.astro"; +import TestCools from "../components/TestCool"; +--- + + + \ No newline at end of file diff --git a/src/pages/topic.astro b/src/pages/topic.astro new file mode 100644 index 0000000..b041d43 --- /dev/null +++ b/src/pages/topic.astro @@ -0,0 +1,7 @@ +--- +import Layout from "../layouts/Layout.astro"; +import TopicList from "../components/Topic"; +--- + + + \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index b24627f..b157276 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1919,7 +1919,7 @@ jiti@^1.21.6, jiti@>=1.21.0: resolved "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz" integrity sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A== -js-tokens@^4.0.0: +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== @@ -1983,6 +1983,13 @@ longest-streak@^3.0.0: resolved "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz" integrity sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g== +loose-envify@^1.4.0: + version "1.4.0" + resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + lru-cache@^10.2.0, lru-cache@^10.4.3: version "10.4.3" resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz" @@ -2563,7 +2570,7 @@ npm-run-path@^5.1.0: dependencies: path-key "^4.0.0" -object-assign@^4.0.1: +object-assign@^4.0.1, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== @@ -2798,6 +2805,15 @@ prompts@^2.4.2: kleur "^3.0.3" sisteransi "^1.0.5" +prop-types@^15.8.1: + version "15.8.1" + resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz" + integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== + dependencies: + loose-envify "^1.4.0" + object-assign "^4.1.1" + react-is "^16.13.1" + property-information@^6.0.0: version "6.5.0" resolved "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz" @@ -2808,6 +2824,11 @@ property-information@^7.0.0: resolved "https://registry.npmjs.org/property-information/-/property-information-7.0.0.tgz" integrity sha512-7D/qOz/+Y4X/rzSB6jKxKUsQnphO046ei8qxG59mtM3RG3DHgTK81HrxrmoDVINJb8NKT5ZsRbwHvQ6B68Iyhg== +qr.js@0.0.0: + version "0.0.0" + resolved "https://registry.npmjs.org/qr.js/-/qr.js-0.0.0.tgz" + integrity sha512-c4iYnWb+k2E+vYpRimHqSu575b1/wKl4XFeJGpFmrJQz5I88v9aY2czh7s0w36srfCM1sXgC/xpoJz5dJfq+OQ== + queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" @@ -2825,6 +2846,19 @@ radix3@^1.1.2: dependencies: scheduler "^0.25.0" +react-is@^16.13.1: + version "16.13.1" + resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== + +react-qr-code@^2.0.15: + version "2.0.15" + resolved "https://registry.npmjs.org/react-qr-code/-/react-qr-code-2.0.15.tgz" + integrity sha512-MkZcjEXqVKqXEIMVE0mbcGgDpkfSdd8zhuzXEl9QzYeNcw8Hq2oVIzDLWuZN2PQBwM5PWjc2S31K8Q1UbcFMfw== + dependencies: + prop-types "^15.8.1" + qr.js "0.0.0" + react-refresh@^0.14.2: version "0.14.2" resolved "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz" @@ -2879,7 +2913,7 @@ react-to-print@^3.0.5: resolved "https://registry.npmjs.org/react-to-print/-/react-to-print-3.0.5.tgz" integrity sha512-Z15MwMOzYCHWi26CZeFNwflAg7Nr8uWD6FTj+EkfIOjYyjr0MXGbI0c7rF4Fgrbj3XG9hFndb1ourxpPz2RAiA== -"react@^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react@^16.8.0 || ^17.0.0 || ^18.0.0 || ~19", "react@^17.0.2 || ^18.0.0 || ^19.0.0", react@^19.0.0, react@>=16.8.0, react@>=18: +react@*, "react@^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react@^16.8.0 || ^17.0.0 || ^18.0.0 || ~19", "react@^17.0.2 || ^18.0.0 || ^19.0.0", react@^19.0.0, react@>=16.8.0, react@>=18: version "19.0.0" resolved "https://registry.npmjs.org/react/-/react-19.0.0.tgz" integrity sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==