#include "FiveWin.ch"
//----------------------------------------------------------------------------//
function Main()
local oWnd, oWebView
DEFINE WINDOW oWnd
oWebView = TWebView2():New( oWnd )
oWebView:SetHtml( Html() )
ACTIVATE WINDOW oWnd MAXIMIZED ;
ON RESIZE oWebView:SetSize( nWidth, nHeight )
return nil
//----------------------------------------------------------------------------//
function Html()
local cHtml
TEXT INTO cHtml
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tablero de Control Empresarial</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 20px;
background-color: #8b93bb; /* Beige claro */
}
.dashboard {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
}
.ventana {
background-color: white;
border-radius: 8px;
padding: 15px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
transition: all 0.3s ease;
}
.ventana:hover {
transform: translateY(-5px);
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
}
h1 {
text-align: center;
color: #333;
}
h3 {
margin-top: 0;
color: #fff;
display: flex;
align-items: center;
padding: 10px;
border-radius: 5px 5px 0 0;
}
h3 i {
margin-right: 10px;
}
.valor {
font-size: 20px;
font-weight: bold;
color: #333;
margin: 10px 0;
}
.finanzas { background-color: #4CAF50; }
.ventas { background-color: #2196F3; }
.operaciones { background-color: #FFC107; }
.marketing { background-color: #E91E63; }
</style>
</head>
<body>
<h1>Tablero de Control Empresarial</h1>
<div id="dashboard" class="dashboard">
<!-- Las ventanas del dashboard se insertarán aquí dinámicamente -->
</div>
<script>
// Datos de ejemplo (en una aplicación real, estos datos podrían venir de FiveWin)
const datos = {
'ventas_mensuales': 150000,
'compras_mensuales': 100000,
'clientes_activos': 500,
'productos_en_stock': 1000,
'pedidos_pendientes': 50,
'ingresos_anuales': 2000000,
'gastos_anuales': 1500000,
'empleados': 100,
'proyectos_activos': 10,
'tasa_conversion': 3.5,
'satisfaccion_cliente': 4.2,
'crecimiento_ventas': 7.5,
'retorno_inversion': 15.2,
'rotacion_inventario': 12,
'cuentas_por_cobrar': 200000,
'cuentas_por_pagar': 150000,
'flujo_caja': 300000,
'margen_beneficio': 25,
'cuota_mercado': 8.5,
'valor_marca': 5000000
};
function crearVentana(titulo, valor, unidad = '', icono = 'fa-chart-line', categoria = 'finanzas') {
const ventana = document.createElement('div');
ventana.className = 'ventana';
ventana.innerHTML = `
<h3 class="${categoria}"><i class="fas ${icono}"></i>${titulo}</h3>
<p class="valor">${formatearNumero(valor)} ${unidad}</p>
`;
return ventana;
}
function formatearNumero(numero) {
return numero.toLocaleString('es-ES');
}
function inicializarDashboard() {
const dashboard = document.getElementById('dashboard');
const ventanas = [
{ titulo: 'Ventas de Contado', valor: datos.ventas_mensuales, unidad: '$', icono: 'fa-shopping-cart', categoria: 'finanzas' },
{ titulo: 'Ventas en Cuenta Corriente', valor: datos.compras_mensuales, unidad: '$', icono: 'fa-shopping-cart', categoria: 'finanzas' },
{ titulo: 'Compras de Contado', valor: datos.clientes_activos, unidad: '$', icono: 'fa-solid fa-basket-shopping', categoria: 'marketing' },
{ titulo: 'Compras en Cuenta Corriente', valor: datos.productos_en_stock, unidad: '$', icono: 'fa-solid fa-basket-shopping', categoria: 'marketing' },
{ titulo: 'Cobranzas por Recibos', valor: datos.pedidos_pendientes, unidad: '$', icono: 'fa-hand-holding-usd', categoria: 'finanzas' },
{ titulo: 'Otros Ingresos', valor: datos.ingresos_anuales, unidad: '$', icono: 'fa-money-bill-wave', categoria: 'finanzas' },
{ titulo: 'Pagos por Órdenes de Pago', valor: datos.gastos_anuales, unidad: '$', icono: 'fa-file-invoice-dollar', categoria: 'marketing' },
{ titulo: 'Otros Egresos', valor: datos.empleados, unidad: '$', icono: 'fa-solid fa-comment-dollar', categoria: 'marketing' },
{ titulo: 'Saldo CC Clientes a fecha', valor: datos.proyectos_activos, unidad: '$', icono: 'fa-users', categoria: 'finanzas' },
{ titulo: 'Saldo Total CC Clientes', valor: datos.tasa_conversion, unidad: '$', icono: 'fa-users', categoria: 'finanzas' },
{ titulo: 'Saldo CC Proveedores a fecha', valor: datos.satisfaccion_cliente, unidad: '$', icono: 'fa-regular fa-user', categoria: 'marketing' },
{ titulo: 'Saldo Total CC Proveedores', valor: datos.crecimiento_ventas, unidad: '$', icono: 'fa-regular fa-user', categoria: 'marketing' },
{ titulo: 'Cheques a Vencer al', valor: datos.retorno_inversion, unidad: '$', icono: 'fa-solid fa-money-check', categoria: 'operaciones' },
{ titulo: 'Cheques en Cartera', valor: datos.rotacion_inventario, unidad: '$', icono: 'fa-solid fa-money-check', categoria: 'operaciones' },
{ titulo: 'Cheques Recibidos entre', valor: datos.cuentas_por_cobrar, unidad: '$', icono: 'fa-solid fa-money-check', categoria: 'operaciones' },
{ titulo: 'Cheques Transferidos entre', valor: datos.cuentas_por_pagar, unidad: '$', icono: 'fa-solid fa-money-check', categoria: 'operaciones' },
{ titulo: 'Cheques Emitidos', valor: datos.flujo_caja, unidad: '$', icono: 'fa-solid fa-building-columns', categoria: 'ventas' },
{ titulo: 'Transferencias Realizadas', valor: datos.margen_beneficio, unidad: '$', icono: 'fa-exchange-alt', categoria: 'ventas' },
{ titulo: 'Transferencias Recibidas', valor: datos.cuota_mercado, unidad: '$', icono: 'fa-exchange-alt', categoria: 'ventas' }
];
ventanas.forEach(v => {
dashboard.appendChild(crearVentana(v.titulo, v.valor, v.unidad, v.icono, v.categoria));
});
}
// Inicializar el dashboard cuando la página se cargue
window.onload = inicializarDashboard;
</script>
</body>
</html>
ENDTEXT
return cHtml
#include "FiveWin.ch"
FUNCTION Main()
local oWebView, oBtn
Local oWnd, oExBar, oPanelExplorer, oPanelWeb, oPanel, oGet := ARRAY(2), dDesde := DATE(), dHasta := DATE()
REQUEST HB_LANG_ESWIN
REQUEST HB_CODEPAGE_ESMWIN
SET DATE FORMAT "DD/MM/YYYY"
SET 3DLOOK ON
HB_LANGSELECT( 'ESWIN' )
//Si mi aplicacion es MDI asi debería definir la ventana
//DEFINE WINDOW oWnd MDICHILD OF oApp:oWnd TITLE "Dashboard " ICON oApp:oIco
DEFINE WINDOW oWnd TITLE "Dashboard "
*** Paneles
oPanelExplorer := TPanel():New( 0, 0, oWnd:nHeight, 280, oWnd )
oPanelWeb := TPanel():New( 0, 281, oWnd:nHeight, oWnd:nWidth, oWnd )
oExBar := TExplorerBar():New( 0, 0, 250, 300, oPanelExplorer )
oPanelExplorer:oClient = oExBar
oPanel := oExBar:AddPanel( "Seleccionar Fecha", "..\bitmaps\calendar.bmp", 255 )
oPanel:AddLink( "Ventas del Periodo" , { || oWebView:SetHtml(memoread('ventas.html')) }, "..\bitmaps\go.bmp" )
oPanel:AddLink( "Compras del Periodo " , { || oWebView:SetHtml(memoread('compras.html')) }, "..\bitmaps\go.bmp" )
oPanel:AddLink( "Cobros del Periodo" , { || oWebView:SetHtml(memoread('cobros.html')) }, "..\bitmaps\go.bmp" )
oPanel:AddLink( "Pagos del Periodo" , { || oWebView:SetHtml(memoread('pagos.html')) }, "..\bitmaps\go.bmp" )
*/
@170, 15 SAY "Desde Fecha:" OF oPanel TRANSPARENT PIXEL SIZE 40,12
@200, 15 SAY "Hasta Fecha:" OF oPanel TRANSPARENT PIXEL SIZE 40,12
@170,90 GET oGet[1] VAR dDesde OF oPanel PIXEL
@200,90 GET oGet[2] VAR dHasta OF oPanel PIXEL
@230,50 BUTTON oBtn PROMPT "Cambiar Fechas" OF oPanel PIXEL SIZE 110,25
oWebView := TWebView2():New(oPanelWeb)
oWebView:SetUserAgent( "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.53 Mobile Safari/537.36" )
oWebView:SetHtml( memoread( 'ventas.html' ) )
oWebView:Run()
ACTIVATE WINDOW oWnd MAXIMIZED ON RESIZE (oPanelExplorer:Move( , , , oWnd:nHeight ),;
oPanelWeb:Move ( , , oWnd:nWidth - oPanelExplorer:nRight, oWnd:nHeight - 60 ),;
oWebView:SetSize(oPanelWeb:nWidth,oPanelWeb:nHeight));
ON INIT (oWebView:SetSize(oPanelWeb:nWidth,oPanelWeb:nHeight),oWnd:Move(0,0))
//Si mi app es MDI deberia agregar aqui
//ON INIT (oWnd:SetSize(oApp:oWnd:oWndclient:nWidth, oApp:oWnd:oWndclient:nHeight)
RETURN nil
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dashboard</title>
<script src="https://cdn.tailwindcss.com"></script>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.12.1/css/all.css" crossorigin="anonymous">
<script type="text/javascript">
// Cargar Google Charts
google.charts.load('current', {'packages':['corechart']});
google.charts.setOnLoadCallback(drawCharts);
// Función para dibujar los gráficos
function drawCharts() {
drawPieChart();
drawLineChart();
}
// Gráfico de torta
function drawPieChart() {
var data = google.visualization.arrayToDataTable([
['Concepto', 'Importe'],
['Efectivo', 800000],
['Mercadopago', 200000],
['Tarjetas', 300000],
['Transferencias', 500000],
['Otros', 150000]
]);
var options = {
title: 'Ingresos por ventas',
widht: '100%',
height: 300,
is3D: true
};
var chart = new google.visualization.PieChart(document.getElementById('piechart'));
chart.draw(data, options);
}
// Gráfico de líneas
function drawLineChart() {
var data = google.visualization.arrayToDataTable([
['Rubro', 'Totales'],
['Carniceria', 1000000],
['Fiambreria', 1170000],
['Comestibles', 660000],
['Bazar', 1030000]
]);
var options = {
title: 'Ventas Por Rubro',
curveType: 'function',
legend: { position: 'bottom' },
widht: '100%',
height: 300,
is3D: true
};
var chart = new google.visualization.ColumnChart(document.getElementById('linechart'));
chart.draw(data, options);
}
window.onresize = function () {
drawCharts(); // Redibujar gráficos cuando la ventana cambia de tamaño
};
</script>
</head>
<body class="bg-gray-100">
<div class="flex flex-col lg:flex-row min-h-screen">
<!-- Sidebar -->
<!-- Main Content -->
<div class="flex-1 p-8 overflow-y-auto">
<!-- Valores Section -->
<div id="values" class="section">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<!-- Ingresos -->
<div class="bg-white shadow-md p-6 h-50 rounded-lg text-center border-t-4 border-green-500">
<h3 class="text-lg font-bold text-green-500"><i class="fas fa-dollar-sign fa-3x"></i></h3>
<p class="text-xl mt-4 text-gray-700">Ventas</p>
<p class="text-3xl mt-2 text-green-500 font-bold">$1,000,000</p>
</div>
<!-- Productos -->
<div class="bg-white shadow-md p-6 h-50 rounded-lg text-center border-t-4 border-blue-500">
<h3 class="text-lg font-bold text-blue-500"><i class="fas fa-boxes fa-3x"></i></h3>
<p class="text-xl mt-4 text-gray-700">Costo</p>
<p class="text-3xl mt-2 text-blue-500 font-bold">$900,000</p>
</div>
<!-- Usuarios -->
<div class="bg-white shadow-md p-6 h-50 rounded-lg text-center border-t-4 border-yellow-500">
<h3 class="text-lg font-bold text-yellow-500"><i class="fas fa-users fa-3x"></i></h3>
<p class="text-xl mt-4 text-gray-700">Unidades</p>
<p class="text-3xl mt-2 text-yellow-500 font-bold">12,000</p>
</div>
</div>
</div>
<div class="section p-2">
<hr>
</div>
<!-- Gráficos Section -->
<div id="charts" class="section">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-2 gap-6">
<div class="bg-white shadow-md p-6 rounded-lg">
<h2 class="text-xl font-bold mb-4 text-green-500">Ventas</h2>
<div id="piechart"></div>
</div>
<div class="bg-white shadow-md p-6 rounded-lg">
<h2 class="text-xl font-bold mb-4 text-blue-500">Por Rubro</h2>
<div id="linechart"></div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
#include "FiveWin.ch"
FUNCTION Main()
local oWebView, oBtn
Local oWnd, oExBar, oPanelExplorer, oPanelWeb, oPanel, oGet := ARRAY(2), dDesde := DATE(), dHasta := DATE()
REQUEST HB_LANG_ESWIN
REQUEST HB_CODEPAGE_ESMWIN
SET DATE FORMAT "DD/MM/YYYY"
SET 3DLOOK ON
HB_LANGSELECT( 'ESWIN' )
//Si mi aplicacion es MDI asi debería definir la ventana
//DEFINE WINDOW oWnd MDICHILD OF oApp:oWnd TITLE "Dashboard " ICON oApp:oIco
DEFINE WINDOW oWnd TITLE "Dashboard "
*** Paneles
oPanelExplorer := TPanel():New( 0, 0, oWnd:nHeight, 280, oWnd )
oPanelWeb := TPanel():New( 0, 281, oWnd:nHeight, oWnd:nWidth, oWnd )
oExBar := TExplorerBar():New( 0, 0, 250, 300, oPanelExplorer )
oPanelExplorer:oClient = oExBar
oPanel := oExBar:AddPanel( "Seleccionar Fecha", "..\bitmaps\calendar.bmp", 255 )
oPanel:AddLink( "Ventas del Periodo" , { || oWebView:SetHtml(MiHtml(1)) }, "..\bitmaps\go.bmp" )
oPanel:AddLink( "Compras del Periodo " , { || oWebView:SetHtml(MiHtml(2)) }, "..\bitmaps\go.bmp" )
oPanel:AddLink( "Cobros del Periodo" , { || oWebView:SetHtml(MiHtml(3)) }, "..\bitmaps\go.bmp" )
oPanel:AddLink( "Pagos del Periodo" , { || oWebView:SetHtml(MiHtml(4)) }, "..\bitmaps\go.bmp" )
oWebView := TWebView2():New(oPanelWeb)
oWebView:SetUserAgent( "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.53 Mobile Safari/537.36" )
oWebView:SetHtml( MiHtml(1) )
oWebView:Run()
ACTIVATE WINDOW oWnd MAXIMIZED ON RESIZE (oPanelExplorer:Move( , , , oWnd:nHeight ),;
oPanelWeb:Move ( , , oWnd:nWidth - oPanelExplorer:nRight, oWnd:nHeight - 60 ),;
oWebView:SetSize(oPanelWeb:nWidth,oPanelWeb:nHeight));
ON INIT (oWebView:SetSize(oPanelWeb:nWidth,oPanelWeb:nHeight),oWnd:Move(0,0))
//Si mi app es MDI deberia agregar aqui
//ON INIT (oWnd:SetSize(oApp:oWnd:oWndclient:nWidth, oApp:oWnd:oWndclient:nHeight)
RETURN nil
STATIC FUNCTION MiHtml(n)
LOCAL oDashBoard, aData
oDashBoard = TDashboard():New()
DO CASE
CASE n = 1
oDashBoard:AddPanel('Ventas','$1,000,000','dollar-sign','green')
oDashBoard:AddPanel('Costo' ,'$900,000','boxes','blue')
oDashBoard:AddPanel('Productos' ,'12,000','cubes','lime')
aData := {{'Carniceria', 1000000},;
{'Fiambreria', 1170000},;
{'Comestibles', 660000},;
{'Bazar', 1030000}}
oDashBoard:AddGraph('Ventas', 'Ventas del periodo', 'PieChart', {'Rubro', 'Totales'}, aData, 'emerald' )
aData := {{'Mercado Pago', 1000000},;
{'Efectivo', 1170000},;
{'Tarjeta', 660000},;
{'Transferencia', 1030000},;
{'Cuenta Corriente', 1030000}}
oDashBoard:AddGraph('Cobros', 'Por Forma de pago', 'ColumnChart', {'Concepto', 'Importe'}, aData, 'purple' )
CASE n = 2
oDashBoard:AddPanel('Compras','$750,000','dollar-sign','emerald')
oDashBoard:AddPanel('Gastos' ,'$350,000','desktop','indigo')
oDashBoard:AddPanel('Stock' ,'7,000','cubes','indigo')
oDashBoard:AddPanel('Reciclado' ,'$90,000','recycle','purple')
aData := {{'Materia Prima', 300000},;
{'Productos Compraventa', 850000},;
{'Gastos', 690000}}
oDashBoard:AddGraph('Compras', 'Por Tipo de compra', 'BarChart', {'Concepto', 'Importe'}, aData, 'purple' )
CASE n = 3
oDashBoard:AddPanel('Tarjetas','$960,000','credit-card','pink')
oDashBoard:AddPanel('Efectivo','$1,050,000','dollar-sign','blue')
CASE n = 4
oDashBoard:AddPanel('Transferencias','$660,000','university','cyan')
oDashBoard:AddPanel('Efectivo','$550,000','dollar-sign','orange')
ENDCASE
RETURN oDashBoard:cHtml
********************************************
** Generar Html
CLASS TDashboard
DATA cHtml
DATA aGraph INIT {}
METHOD New() CONSTRUCTOR
METHOD AddPanel(cTexto, cValor, cFaFaIcon, cColor )
METHOD AddGraph (cNombre, cTitulo, cTipo, aColumnsData, aData, cColor )
ENDCLASS
//----------------------------------------------------------------//
METHOD New() CLASS TDashboard
TEXT INTO ::cHtml
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dashboard</title>
<script src="https://cdn.tailwindcss.com"></script>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.12.1/css/all.css" crossorigin="anonymous">
<script type="text/javascript">
// Cargar Google Charts
google.charts.load('current', {'packages':['corechart']});
google.charts.setOnLoadCallback(drawCharts);
// Función para dibujar los gráficos
function drawCharts() {
//AgregarChar
}
//FuncionGrafico
window.onresize = function () {
drawCharts(); // Redibujar gráficos cuando la ventana cambia de tamaño
};
</script>
</head>
<body class="bg-gray-100">
<div class="flex flex-col lg:flex-row min-h-screen">
<!-- Main Content -->
<div class="flex-1 p-8 overflow-y-auto">
<div id="values" class="section">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<!-- AddPanel -->
</div>
</div>
<div class="section p-2">
<hr>
</div>
<!-- Gráficos Section -->
<div id="charts" class="section">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-2 gap-6">
<!-- idgrafico -->
</div>
</div>
</div>
</div>
</body>
</html>
ENDTEXT
return Self
METHOD AddPanel(cTexto, cValor, cFaFaIcon, cColor ) CLASS TDashboard
Local cPanel := '<div class="bg-white shadow-md p-6 h-50 rounded-lg text-center border-t-4 border-'+cColor+'-500">'+;
' <h3 class="text-lg font-bold text-'+cColor+'-500"><i class="fas fa-'+cFaFaIcon+' fa-3x"></i></h3>'+;
' <p class="text-xl mt-4 text-'+cColor+'-700">'+cTexto+'</p>'+;
' <p class="text-3xl mt-2 text-'+cColor+'-500 font-bold">'+cValor+'</p>'+;
'</div>'+;
'<!-- AddPanel -->'
::cHtml := strtran(::cHtml,"<!-- AddPanel -->",cPanel)
return Self
METHOD AddGraph (cNombre, cTitulo, cTipo, aColumnsData, aData, cColor )
Local cGraph, cFuncion, cId, i
cGraph := cNombre+'();//AgregarChar'
::cHtml := strtran(::cHtml,"//AgregarChar",cGraph)
cFuncion := "function "+cNombre+"() { "+;
"var data = google.visualization.arrayToDataTable(["+;
" ['"+aColumnsData[1]+"', '"+aColumnsData[2]+"'], "
for i := 1 to len(aData)
cFuncion := cFuncion + "['"+aData[i,1]+"', "+STR(aData[i,2])+"],"
next i
cFuncion := cFuncion + " ]);"+;
"var options = { "+;
" title: '"+cTitulo+"',"+;
" widht: '100%',"+;
" height: 300, "+;
" is3D: true "+;
"};"+;
"var chart = new google.visualization."+cTipo+"(document.getElementById('"+cNombre+"'));"+;
"chart.draw(data, options);"+;
"}"+;
"//FuncionGrafico"
::cHtml := strtran(::cHtml,"//FuncionGrafico",cFuncion)
cId := '<div class="bg-white shadow-md p-6 rounded-lg">'+;
'<h2 class="text-xl font-bold mb-4 text-'+cColor+'-500">'+cTitulo+'</h2>'+;
'<div id="'+cNombre+'"></div>'+;
'</div>'+;
'<!-- idgrafico -->'
::cHtml := strtran(::cHtml,"<!-- idgrafico -->",cId)
return Self
#include "FiveWin.ch"
function Main()
local oWnd, oExplBar, oExplPanel, oWebView
local cCategory := Space( 30 )
DEFINE WINDOW oWnd TITLE "Build it"
oExplBar = TExplorerBar():New( 0, 82, 480, 100, oWnd:oLeft )
oWnd:oLeft = oExplBar
oExplBar:AddPanel( "My App" )
oExplPanel = oExplBar:AddPanel( "AI assistant" )
oExplPanel:AddLink( "what is this app about ?",;
{ || MsgGet( "App category", "Please specify it", @cCategory ) } )
oWnd:oClient = TPanel():New( 0, 0, 100, 100, oWnd )
oWebView = TWebView2():New( oWnd:oClient )
oWebView:Navigate( "https://www.google.com" )
ACTIVATE WINDOW oWnd MAXIMIZED ;
ON RESIZE ( oWebView:SetSize( nWidth - oExplBar:nWidth, nHeight ), oExplBar:SetSize( 480, nHeight ) )
return nil
Antonio Linares wrote:He simplificado mucho el modelo con la idea de usar la inteligencia artificial para hacer el trabajo
#include "FiveWin.ch"
// get your OpenAI key from https://platform.openai.com/api-keys
static cKey := "sk-proj-..."
static oChatgpt
static oTree
static cCategory := " "
function Main()
local oWnd, oExplBar, oAppPanel, oExplPanel, oWebView
oChatgpt = TChatgpt():New( cKey )
DEFINE WINDOW oWnd TITLE "Build it"
oExplBar = TExplorerBar():New( 0, 82, 480, 100, oWnd:oLeft, CLR_WHITE, RGB( 31, 31, 31 ) )
oWnd:oLeft = oExplBar
oExplPanel = oExplBar:AddPanel( "AI assistant" )
oExplPanel:AddLink( "what is this app about ?",;
{ || If( MsgGet( "App category", "Please specify it", @cCategory ), AddOptions( cCategory, oExplBar ),) } )
oExplPanel:AddLink( "Add options to selected item", { || AddSubOptions() } )
oWnd:oClient = TPanel():New( 0, 0, 100, 100, oWnd )
oWebView = TWebView2():New( oWnd:oClient )
oWebView:Navigate( "https://www.google.com" )
ACTIVATE WINDOW oWnd MAXIMIZED ;
ON RESIZE ( oWebView:SetSize( nWidth - oExplBar:nWidth, nHeight ), oExplBar:SetSize( 480, nHeight ) )
return nil
function AddOptions( cCategory, oExplBar )
local cOptions, aOptions, cOption, oAppPanel
oChatgpt:cPrompt := "genera una lista separada por comas con las opciones de una aplicación de " + AllTrim( cCategory ) + ;
". No des ninguna explicación"
oChatgpt:Send()
cOptions = oChatgpt:GetValue( "choices", "message", "content" )
aOptions = hb_ATokens( cOptions, "," )
oAppPanel = oExplBar:AddPanel( cCategory,, 700 )
oTree = TTreeView():New( 2.5, 2, oAppPanel,,,,, 423, 675 )
for each cOption in aOptions
oTree:Add( cOption )
next
return nil
function AddSubOptions()
local oItem
local cOption := If( ( oItem := oTree:GetSelected() ) != nil, oItem:cPrompt, "" )
local cOptions, cSubOption, aOptions
if ! Empty( cOption )
oChatgpt:cPrompt := "genera una lista separada por comas con las opciones de " + cOption + ;
" para una aplicación de " + cCategory + ". No des ninguna explicación"
oChatgpt:Send()
cOptions = oChatgpt:GetValue( "choices", "message", "content" )
aOptions = hb_ATokens( cOptions, "," )
for each cSubOption in aOptions
oItem:Add( cSubOption )
next
oItem:Expand()
endif
return nil
#include "FiveWin.ch"
#include "hbcurl.ch"
//----------------------------------------------------------------------------//
CLASS TChatgpt
DATA cKey AS CHARACTER INIT ""
DATA hCurl
DATA nHttpCode
DATA nError INIT 0
DATA cResponse
DATA cPrompt
DATA cModel INIT "gpt-4o-mini"
DATA cUrl INIT "https://api.openai.com/v1/chat/completions"
METHOD New( cKey )
METHOD End()
METHOD Send()
METHOD Reset()
METHOD GetValue( ... )
ENDCLASS
//----------------------------------------------------------------------------//
METHOD New( cKey ) CLASS TChatgpt
::cKey := cKey
::hCurl := curl_easy_init()
return Self
//----------------------------------------------------------------------------//
METHOD Send() CLASS TChatgpt
local aheaders, nHttpCode, cJson, h := { => }, hMessage := { => }
curl_easy_setopt( ::hCurl, HB_CURLOPT_POST, .T. )
curl_easy_setopt( ::hCurl, HB_CURLOPT_URL, ::cUrl )
aheaders := { "Content-Type: application/json", ;
"Authorization: Bearer " + ::cKey }
curl_easy_setopt( ::hCurl, HB_CURLOPT_HTTPHEADER, aheaders )
curl_easy_setopt( ::hCurl, HB_CURLOPT_USERNAME, '' )
curl_easy_setopt( ::hCurl, HB_CURLOPT_DL_BUFF_SETUP )
curl_easy_setopt( ::hCurl, HB_CURLOPT_SSL_VERIFYPEER, .F. )
hb_HSet( h, "model", ::cModel )
hb_HSet( hMessage, "role", "user" )
hb_HSet( hMessage, "content", ::cPrompt )
h["messages"] = { hMessage }
cJson = hb_jsonEncode( h )
curl_easy_setopt( ::hcurl, HB_CURLOPT_POSTFIELDS, cJson )
::nError = curl_easy_perform( ::hCurl )
curl_easy_getinfo( ::hCurl, HB_CURLINFO_RESPONSE_CODE, @nHttpCode )
::nHttpCode = nHttpCode
if ::nError == HB_CURLE_OK
::cResponse = curl_easy_dl_buff_get( ::hCurl )
else
endif
return ::cResponse
//----------------------------------------------------------------------------//
METHOD Reset() CLASS TChatgpt
curl_easy_reset( ::hCurl )
::nError := HB_CURLE_OK
::cResponse := nil
return nil
//----------------------------------------------------------------------------//
METHOD End() CLASS TChatgpt
curl_easy_cleanup( ::hCurl )
::hCurl := nil
return nil
//----------------------------------------------------------------------------//
METHOD GetValue( ... ) CLASS TChatgpt
local aKeys := hb_AParams(), cKey
local uValue := hb_jsonDecode( ::cResponse )
for each cKey in aKeys
if ValType( uValue[ cKey ] ) == "A"
uValue = uValue[ cKey ][ 1 ]
else
uValue = uValue[ cKey ]
endif
next
return uValue
//----------------------------------------------------------------------------//
Return to FiveWin para Harbour/xHarbour
Users browsing this forum: cmsoft and 55 guests