init commit

This commit is contained in:
Jose
2025-08-03 05:52:49 +02:00
commit ef495b7529
15 changed files with 324 additions and 0 deletions

13
index.html Normal file
View File

@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title></title>
</head>
<body>
<div id="root" class="p-0 m-0"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>

9
jsconfig.json Normal file
View File

@@ -0,0 +1,9 @@
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
},
"include": ["src"]
}

39
package.json Normal file
View File

@@ -0,0 +1,39 @@
{
"name": "miarma-base",
"private": true,
"version": "1.0.0",
"scripts": {
"dev": "vite",
"build": "vite build",
"lint": "eslint .",
"preview": "vite preview"
},
"dependencies": {
"@fortawesome/fontawesome-free": "^7.0.0",
"@fortawesome/fontawesome-svg-core": "^7.0.0",
"@fortawesome/free-brands-svg-icons": "^7.0.0",
"@fortawesome/free-regular-svg-icons": "^7.0.0",
"@fortawesome/free-solid-svg-icons": "^7.0.0",
"@fortawesome/react-fontawesome": "^0.2.3",
"axios": "^1.11.0",
"bootstrap": "^5.3.7",
"date-fns": "^4.1.0",
"framer-motion": "^12.23.12",
"react": "^19.1.0",
"react-bootstrap": "^2.10.10",
"react-dom": "^19.1.0",
"react-router-dom": "^7.7.1"
},
"devDependencies": {
"@eslint/js": "^9.30.1",
"@types/react": "^19.1.8",
"@types/react-dom": "^19.1.6",
"@vitejs/plugin-react": "^4.6.0",
"electron": "^37.2.5",
"eslint": "^9.30.1",
"eslint-plugin-react-hooks": "^5.2.0",
"eslint-plugin-react-refresh": "^0.4.20",
"globals": "^16.3.0",
"vite": "^7.0.4"
}
}

View File

@@ -0,0 +1 @@
{}

View File

@@ -0,0 +1 @@
{}

BIN
public/fonts/OpenSans.ttf Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

13
src/App.jsx Normal file
View File

@@ -0,0 +1,13 @@
import 'bootstrap/dist/css/bootstrap.min.css'
import 'bootstrap/dist/js/bootstrap.bundle.min.js'
const App = () => {
return (
<>
<h1>Hola!</h1>
<a href="https://gallardo.dev">Abre este link</a>
</>
)
}
export default App

88
src/css/index.css Normal file
View File

@@ -0,0 +1,88 @@
/* ================================
FUENTES PERSONALIZADAS
================================== */
@font-face {
font-family: "Open Sans";
src: url('/fonts/OpenSans.ttf');
}
@font-face {
font-family: "Product Sans";
src: url('/fonts/ProductSansRegular.ttf');
}
@font-face {
font-family: "Product Sans Italic";
src: url('/fonts/ProductSansItalic.ttf');
}
@font-face {
font-family: "Product Sans Italic Bold";
src: url('/fonts/ProductSansBoldItalic.ttf');
}
@font-face {
font-family: "Product Sans Bold";
src: url('/fonts/ProductSansBold.ttf');
}
/* ================================
PALETA DE COLORES
================================== */
:root {
}
/* Tema Claro */
.light {
}
/* Tema Oscuro */
.dark {
}
/* ================================
ESTILOS BASE / RESET SUAVE
================================== */
html,
body {
font-family: "Open Sans", sans-serif;
color: var(--text-color);
background-color: var(--bg-color);
}
body {
background-color: transparent !important; /* compatibilidad navbar fija */
}
main {
color: var(--text-color);
background-color: var(--bg-color);
}
/* Tipografía global */
div,
label,
input,
p,
span,
a,
button {
font-family: "Open Sans", sans-serif;
color: var(--text-color);
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-family: "Product Sans", sans-serif;
color: var(--text-color);
}

130
src/hooks/useData.js Normal file
View File

@@ -0,0 +1,130 @@
import { useState, useEffect, useCallback, useRef } from "react";
import axios from "axios";
export const useData = (config) => {
const [data, setData] = useState(null);
const [dataLoading, setLoading] = useState(true);
const [dataError, setError] = useState(null);
const configRef = useRef();
useEffect(() => {
if (config?.baseUrl) {
configRef.current = config;
}
}, [config]);
const getAuthHeaders = () => ({
"Content-Type": "application/json",
"Authorization": `Bearer ${localStorage.getItem("token")}`,
});
const fetchData = useCallback(async () => {
const current = configRef.current;
if (!current?.baseUrl) return;
setLoading(true);
setError(null);
try {
const response = await axios.get(current.baseUrl, {
headers: getAuthHeaders(),
params: current.params,
});
setData(response.data.data);
} catch (err) {
setError(err.response?.data?.message || err.message);
} finally {
setLoading(false);
}
}, []);
useEffect(() => {
if (config?.baseUrl) {
fetchData();
}
}, [config, fetchData]);
const getData = async (url, params = {}) => {
try {
const response = await axios.get(url, {
headers: getAuthHeaders(),
params,
});
return { data: response.data.data, error: null };
} catch (err) {
return {
data: null,
error: err.response?.data?.message || err.message,
};
}
};
const postData = async (endpoint, payload) => {
const headers = {
Authorization: `Bearer ${localStorage.getItem("token")}`,
...(payload instanceof FormData ? {} : { "Content-Type": "application/json" }),
};
const response = await axios.post(endpoint, payload, { headers });
await fetchData();
return response.data.data;
};
const postDataValidated = async (endpoint, payload) => {
try {
const headers = {
Authorization: `Bearer ${localStorage.getItem("token")}`,
...(payload instanceof FormData ? {} : { "Content-Type": "application/json" }),
};
const response = await axios.post(endpoint, payload, { headers });
return { data: response.data.data, errors: null };
} catch (err) {
const raw = err.response?.data?.message;
let parsed = {};
try {
parsed = JSON.parse(raw);
} catch {
return { data: null, errors: { general: raw || err.message } };
}
return { data: null, errors: parsed };
}
};
const putData = async (endpoint, payload) => {
const response = await axios.put(endpoint, payload, {
headers: getAuthHeaders(),
});
await fetchData();
return response.data.data;
};
const deleteData = async (endpoint) => {
const response = await axios.delete(endpoint, {
headers: getAuthHeaders(),
});
await fetchData();
return response.data.data;
};
const deleteDataWithBody = async (endpoint, payload) => {
const response = await axios.delete(endpoint, {
headers: getAuthHeaders(),
data: payload,
});
await fetchData();
return response.data.data;
};
return {
data,
dataLoading,
dataError,
getData,
postData,
postDataValidated,
putData,
deleteData,
deleteDataWithBody,
};
};

13
src/main.jsx Normal file
View File

@@ -0,0 +1,13 @@
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import '@/css/index.css'
import App from '@/App.jsx'
import { BrowserRouter } from 'react-router-dom'
createRoot(document.getElementById('root')).render(
<StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</StrictMode>
)

17
vite.config.js Normal file
View File

@@ -0,0 +1,17 @@
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import path from 'path'
// https://vite.dev/config/
export default defineConfig({
plugins: [react()],
server: {
host: "localhost",
port: 3000,
},
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
},
},
})