Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/data/dataset.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export const characters = [
export default [
{
"id": "daphne-bridgerton",
"name": "Daphne Bridgerton",
Expand Down
22 changes: 12 additions & 10 deletions src/index.html
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Add your CSS and other head elements here -->
</head>
<body>

<div id="root"></div> <!-- This is your root element -->
<script type="module" src="main.js"></script>
</body>
</html>
<html>
<body>
<head>
<meta charset="utf-8">
<title>Dataverse Chat</title>
<link rel="stylesheet" href="style.css"/>
</head>
<div id="root">
</div>
<script type="module" src="./index.js"></script>
</body>
</html>
44 changes: 12 additions & 32 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,49 +1,29 @@
import { Home } from './views/home';
import { ApiKey } from './views/ApiKey';
import { ChatIndividual } from './views/chatIndividual';
import { Error } from './views/error';
import home from './views/home.js';
import ApiKey from './views/ApiKey.js';
import chatIndividual from './views/chatIndividual.js';
import PageError from './views/PageError.js';
import { setRootEl, setRoutes, onURLChange } from './router.js';
import { CharacterList } from './components/CharacterList.js';
import { Statistics } from './components/Statistics.js';

const prueba = document.getElementById('root');

const routes = {
'/': Home,
'/apikey': ApiKey,
'/chat': ChatIndividual,
'/error': Error
"/": home,
"/ApiKey": ApiKey,
"/chatIndividual": chatIndividual,
"/PageError": PageError,
};

setRoutes(routes);

window.addEventListener("DOMContentLoaded", () => {
setRootEl(document.getElementById('root'));
setRootEl(prueba);
onURLChange(window.location);
});

window.addEventListener('popstate', () => {
window.addEventListener("popstate", () => {
onURLChange(window.location);
});

// Function to handle filtering and sorting in SPA
function handleFiltersAndSorting() {
const familyFilter = document.querySelector('#family-filter').value;
const sortFilter = document.querySelector('#alfabetico').value;

const characterList = CharacterList({ familyFilter, sortFilter });
document.getElementById('root').appendChild(characterList);
}

document.querySelector('#family-filter').addEventListener('change', handleFiltersAndSorting);
document.querySelector('#alfabetico').addEventListener('change', handleFiltersAndSorting);

document.querySelector('#calcularEstadisticas').addEventListener('click', () => {
const characters = getCharacters();
const stats = Statistics({ characters });
document.getElementById('resultado-estadisticas').innerHTML = '';
document.getElementById('resultado-estadisticas').appendChild(stats);
});


/*
TODO:
1.- Definir rutas en router.
Expand Down
52 changes: 52 additions & 0 deletions src/lib/dataFunction.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
export const filterData = (data, filterBy, value) => {
return data.filter(character =>
character.facts[filterBy].toLowerCase() === value.toLowerCase()
);
};


export const sortData = (data, sortBy, sortOrder) => {
// exportamos la función para ordenar personajes por nombre
//data:array de objeto(personajes),sortBy:campo del objeto,sortOrder: asc-des
const sortedCharacters = [...data];
//crea un nuevo array(copia)que contiene todos los elementos del array
return sortedCharacters.sort((a, b) => {
//compara cada par de elementos y luego retorna el array ordenado.
if (sortOrder === 'asc') {
//si es excatamente igual se ordena de forma ascendente
return a[sortBy].localeCompare(b[sortBy]);
//método de las cadenas de texto en JS que compara dos cadenas de texto
} else if (sortOrder === 'des') {
//ademas si ...
return b[sortBy].localeCompare(a[sortBy]);
//comparacion a la inversa (desendente)

}
});
};

export const computeStats = (data) => {
return data.reduce((estadisticas, character) => {
// Función para calcular estadísticas usando reduce
const sitSentimental = character.facts.sitSentimental.toLowerCase();
//accede a la propiedad sitSentimental de un objeto character
//y almacena el resultado en la constante sitSentimental

if (sitSentimental.includes("casad")) {
estadisticas.casados++;
} else if (sitSentimental.includes("solter")) {
estadisticas.solteros++;
} else if (sitSentimental.includes("viud")) {
estadisticas.viudos++;
} else if (sitSentimental.includes("amante")) {
estadisticas.amantes++;
}
return estadisticas;
}, {
casados: 0,
solteros: 0,
viudos: 0,
amantes: 0
//contador con el que inicializan los contadores
});
};
4 changes: 2 additions & 2 deletions src/main.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
import { ApiKey } from './views/ApiKey';
//marcia nos dijo que colocaramos el import aquí
// import { ApiKey } from './views/ApiKey';
//marcia nos dijo que colocaramos el import aquí...
63 changes: 14 additions & 49 deletions src/router.js
Original file line number Diff line number Diff line change
@@ -1,58 +1,23 @@
let rootEl;

let ROUTES = {};
let rootEl = null;

// Función para establecer el elemento raíz donde se renderizan las vistas
export const setRootEl = (el) => {
export function setRootEl(el) {
rootEl = el;
}

// Función para establecer las rutas
export const setRoutes = (routes) => {
if (typeof routes !== 'object') {
throw new Error('Las rutas deben ser un objeto');
}
if (!routes['/error']) {
throw new Error('Las rutas deben definir una ruta /error');
}
ROUTES = routes;
};

// Función para convertir los parámetros de búsqueda en un objeto
const queryStringToObject = (queryString) => {
const params = new URLSearchParams(queryString);
const obj = {};
for (const [key, value] of params.entries()) {
obj[key] = value;
}
return obj;
}

// Función para renderizar la vista basada en la ruta
const renderView = (pathname, props = {}) => {
if (rootEl) {
rootEl.innerHTML = ''; // Limpiar el elemento raíz
// Obtener la vista correspondiente o la vista de error
const View = ROUTES[pathname] || ROUTES['/error'];
// Renderizar la vista pasando los props
const viewEl = View(props);
rootEl.appendChild(viewEl); // Agregar la vista al DOM
}
export function setRoutes(routes) {
window.routes = routes;
}

// Función para navegar a una nueva ruta
export const navigateTo = (pathname, props = {}) => {
// Actualizar el historial
window.history.pushState({}, '', pathname);
// Renderizar la vista correspondiente
renderView(pathname, props);
export function onURLChange(location) {
const path = location.pathname;
const route = window.routes[path] || window.routes['/error'];
const view = route();

rootEl.innerHTML = ''; // Limpia el contenedor antes de agregar la nueva vista
rootEl.appendChild(view);
}

// Función para manejar cambios en la URL
export const onURLChange = (location) => {
const pathname = location.pathname;
// Convertir los parámetros de búsqueda en objeto
const searchParams = queryStringToObject(location.search);
// Renderizar la vista basada en la ruta y los parámetros de búsqueda
renderView(pathname, searchParams);
export function navigateTo(path) {
window.history.pushState({}, path, window.location.origin + path);
onURLChange(window.location);
}
10 changes: 8 additions & 2 deletions src/views/ApiKey.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
//Crea un nuevo elemento div,le asigna texto como su contenido
// y devuelve ese div para que se pueda utilizar en otras partes
export function ApiKey(props) {
export function ApiKey() {
const viewEl = document.createElement('div');
viewEl.textContent = '¡Este es el Api Key!';
viewEl.innerHTML = `
<h2>Configuración de API Key</h2>
<p>Ingresa tu clave API para acceder al chat.</p>
<input type="text" placeholder="Tu API Key aquí" />
<button>Guardar</button>
`;
return viewEl;
}
export default ApiKey;
7 changes: 7 additions & 0 deletions src/views/PageError.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export function PageError() { // exportamos la función ErrorPage que devuelve un elemento HTML
const viewEl = document.createElement('div'); // Creamos un contenedor para la vista de error
viewEl.innerHTML = '<h1>Error 404</h1><p>¡Página no encontrada!</p>'; // Establecemos el contenido de la vista
return viewEl; // Retornamos el elemento creado
}
export default PageError;

12 changes: 9 additions & 3 deletions src/views/chatIndividual.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
export function ChatIndividual(props) {
export function chatIndividual() {
const viewEl = document.createElement('div');
viewEl.textContent = '¡Este es el chatINdividual!';
viewEl.innerHTML = `
<h2>Chat Individual</h2>
<p>Aquí puedes chatear con un personaje seleccionado.</p>
<div id="chat-container">
<!-- Aquí irá el contenido del chat -->
</div>
`;
return viewEl;
}

export default chatIndividual;
6 changes: 0 additions & 6 deletions src/views/error.js

This file was deleted.

8 changes: 6 additions & 2 deletions src/views/home.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
export function Home(props) {
export function home() {
const viewEl = document.createElement('div');
viewEl.textContent = '¡Este es el home!';
viewEl.innerHTML = `
<h1>Bienvenido al Dataverse Chat</h1>
<p>Explora y conéctate con otros personajes.</p>
`;
return viewEl;
}
export default home;
50 changes: 50 additions & 0 deletions test/dataFunction.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// test/dataFunctions.spec.js
import data from '../src/data/dataset.js'; //importamos el dataset
import { filterData } from '../src/lib/dataFunction.js';
import { sortData } from '../src/lib/dataFunction.js';
import { computeStats } from '../src/lib/dataFunction.js';

describe('filterData', () => {
it('returns characters from the Bridgerton family', () => {
const result = filterData(data, 'familia', 'Bridgerton'); // Filtra la familia "Bridgerton": Utiliza filterData para obtener todos los personajes que pertenecen a la familia "Bridgerton".
const expectedCharacters = data.filter(character => character.facts.familia === 'Bridgerton'); // Esto filtra el dataset original para obtener el array de personajes que coinciden con la familia "Bridgerton" y compara con el resultado de filterData
expect(result).toEqual(expectedCharacters); // Compara ambos resultados
});

it('returns an empty array if no characters match the family', () => { //Filtra la familia "Featherington": Similar a la primera prueba, pero busca personajes de la familia "Featherington".
const result = filterData(data, 'familia', 'Featherington');
const expectedCharacters = data.filter(character => character.facts.familia === 'Featherington'); //Si ningún personaje coincide con la familia, se espera que la función retorne un array vacío.

expect(result).toEqual(expectedCharacters);
});
});

const getExpectedSortedData = (data, order) => {
return [...data].sort((a, b) => {
if (order === 'asc') return a.name.localeCompare(b.name);
if (order === 'des') return b.name.localeCompare(a.name);
});
};

describe('sortData', () => {
test('should sort data by name in ascending order', () => {
expect(sortData(data, 'name', 'asc')).toEqual(getExpectedSortedData(data, 'asc'));
});

test('should sort data by name in descending order', () => {
expect(sortData(data, 'name', 'des')).toEqual(getExpectedSortedData(data, 'des'));
});
});

describe('computeStats', () => {
test('should compute correct statistics for sentiment status', () => {
const result = computeStats(data);
const expected = {
casados: 13,
solteros: 5,
viudos: 4,
amantes: 2,
};
expect(result).toEqual(expected);
});
});