Compare commits
4 Commits
629690d29e
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| dfb42c11b4 | |||
| 14b0f1b805 | |||
| 2484cf8191 | |||
| 3e0452c4d7 |
@@ -1,3 +1,6 @@
|
|||||||
# Coord-Keeper
|
# Coord-Keeper
|
||||||
|
|
||||||
Una pequeñisima app que estoy haciendo para almacenar localmente coordenadas de minecraft
|
Una pequeñisima app que estoy haciendo para almacenar localmente coordenadas de minecraft
|
||||||
|
|
||||||
|
|
||||||
|
[Live Demo](https://fedesrv.ddns.net/coords)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
export default function Barra ({active, setType}) {
|
export default function Barra({ active, setType }) {
|
||||||
return (
|
return (
|
||||||
<nav class="navbar navbar-expand-lg bg-dark-subtle h-fit w-100">
|
<nav class="navbar navbar-expand-lg bg-dark-subtle h-fit w-100">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
@@ -6,27 +6,80 @@ export default function Barra ({active, setType}) {
|
|||||||
Coords-Keeper
|
Coords-Keeper
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<div class="justify-content-end">
|
|
||||||
<ul class="navbar-nav">
|
|
||||||
<li className="nav-item">
|
|
||||||
<button
|
<button
|
||||||
className={`btn bg-primary mx-2 ${active === "overworld" ? "text-black active" : "text-gray-100"}`}
|
class="navbar-toggler"
|
||||||
|
type="button"
|
||||||
|
data-bs-toggle="offcanvas"
|
||||||
|
data-bs-target="#offcanvasNavbar"
|
||||||
|
aria-controls="offcanvasNavbar"
|
||||||
|
>
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div class="offcanvas offcanvas-end" tabindex="-1" id="offcanvasNavbar">
|
||||||
|
<div class="offcanvas-header">
|
||||||
|
<h5 class="offcanvas-title">Coords-Keeper</h5>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn-close"
|
||||||
|
data-bs-dismiss="offcanvas"
|
||||||
|
aria-label="Close"
|
||||||
|
></button>
|
||||||
|
</div>
|
||||||
|
<div class="offcanvas-body">
|
||||||
|
<ul class="navbar-nav justify-content-end flex-grow-1">
|
||||||
|
<li className="nav-item">
|
||||||
|
<a
|
||||||
|
className={`nav-link d-lg-none ${active === "overworld" ? "active" : ""}`}
|
||||||
|
onClick={() => {
|
||||||
|
setType("overworld");
|
||||||
|
document
|
||||||
|
.querySelector('[data-bs-dismiss="offcanvas"]')
|
||||||
|
.click();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Overworld
|
||||||
|
</a>
|
||||||
|
<button
|
||||||
|
className={`btn bg-primary mx-2 d-none d-lg-block ${active === "overworld" ? "text-black active" : "text-gray-100"}`}
|
||||||
onClick={() => setType("overworld")}
|
onClick={() => setType("overworld")}
|
||||||
>
|
>
|
||||||
Overworld
|
Overworld
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
<li className="nav-item">
|
<li className="nav-item">
|
||||||
|
<a
|
||||||
|
className={`nav-link d-lg-none ${active === "nether" ? "active" : ""}`}
|
||||||
|
onClick={() => {
|
||||||
|
setType("nether");
|
||||||
|
document
|
||||||
|
.querySelector('[data-bs-dismiss="offcanvas"]')
|
||||||
|
.click();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Nether
|
||||||
|
</a>
|
||||||
<button
|
<button
|
||||||
className={`btn bg-danger mx-2 ${active === "nether" ? "text-black active" : "text-gray-100"}`}
|
className={`btn bg-danger mx-2 d-none d-lg-block ${active === "nether" ? "text-black active" : "text-gray-100"}`}
|
||||||
onClick={() => setType("nether")}
|
onClick={() => setType("nether")}
|
||||||
>
|
>
|
||||||
Nether
|
Nether
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
<li className="nav-item">
|
<li className="nav-item">
|
||||||
|
<a
|
||||||
|
className={`nav-link d-lg-none ${active === "end" ? "active" : ""}`}
|
||||||
|
onClick={() => {
|
||||||
|
setType("end");
|
||||||
|
document
|
||||||
|
.querySelector('[data-bs-dismiss="offcanvas"]')
|
||||||
|
.click();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
End
|
||||||
|
</a>
|
||||||
<button
|
<button
|
||||||
className={`btn bg-success mx-2 ${active === "end" ? "text-black active" : "text-gray-100"}`}
|
className={`btn bg-success mx-2 d-none d-lg-block ${active === "end" ? "text-black active" : "text-gray-100"}`}
|
||||||
onClick={() => setType("end")}
|
onClick={() => setType("end")}
|
||||||
>
|
>
|
||||||
End
|
End
|
||||||
@@ -35,6 +88,7 @@ export default function Barra ({active, setType}) {
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
22
src/components/BotonAdd.jsx
Normal file
22
src/components/BotonAdd.jsx
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
export default function BotonAdd({ show, setshow }) {
|
||||||
|
if (!show) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
className="btn btn-primary rounded-circle position-fixed bottom-0 end-0 m-4 d-flex align-items-center justify-content-center"
|
||||||
|
style={{ width: "60px", height: "60px" }}
|
||||||
|
onClick={() => setshow(true)}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
fill="currentColor"
|
||||||
|
className="bi bi-plus"
|
||||||
|
viewBox="0 0 16 16"
|
||||||
|
>
|
||||||
|
<path d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
import { useState } from "react";
|
import React from "react";
|
||||||
|
|
||||||
export default function EditarModal({ tipo, coord, show, close, setCoords }) {
|
export default function EditarModal({ tipo, coord, show, close, setCoords }) {
|
||||||
if (coord == null) return null;
|
if (coord == null) return null;
|
||||||
const [hasY, setHasY] = useState(coord.y !== null);
|
|
||||||
|
const [showY, setShowY] = React.useState(coord.y !== null);
|
||||||
|
|
||||||
const handleSubmit = (e) => {
|
const handleSubmit = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -11,6 +13,7 @@ export default function EditarModal({ tipo, coord, show, close, setCoords }) {
|
|||||||
const y = formData.get("y");
|
const y = formData.get("y");
|
||||||
const z = formData.get("z");
|
const z = formData.get("z");
|
||||||
const descripcion = formData.get("descripcion");
|
const descripcion = formData.get("descripcion");
|
||||||
|
const hasY = formData.get("hasY") === "true";
|
||||||
|
|
||||||
let storedTipo = localStorage.getItem(tipo);
|
let storedTipo = localStorage.getItem(tipo);
|
||||||
if (storedTipo) {
|
if (storedTipo) {
|
||||||
@@ -20,7 +23,7 @@ export default function EditarModal({ tipo, coord, show, close, setCoords }) {
|
|||||||
arr[index] = {
|
arr[index] = {
|
||||||
...coord,
|
...coord,
|
||||||
x: Number(x),
|
x: Number(x),
|
||||||
y: y ? Number(y) : null,
|
y: hasY ? Number(y) : null,
|
||||||
z: Number(z),
|
z: Number(z),
|
||||||
descripcion: descripcion,
|
descripcion: descripcion,
|
||||||
};
|
};
|
||||||
@@ -57,12 +60,11 @@ export default function EditarModal({ tipo, coord, show, close, setCoords }) {
|
|||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
|
name="hasY"
|
||||||
|
value="true"
|
||||||
className="form-check-input me-2"
|
className="form-check-input me-2"
|
||||||
checked={hasY}
|
defaultChecked={coord.y !== null}
|
||||||
onChange={(e) => {
|
onChange={(e) => setShowY(e.target.checked)}
|
||||||
coord.y = e.target.checked ? "0" : null;
|
|
||||||
setHasY(e.target.checked);
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
<label className="form-label">Lleva coordenada Y?</label>
|
<label className="form-label">Lleva coordenada Y?</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -75,7 +77,7 @@ export default function EditarModal({ tipo, coord, show, close, setCoords }) {
|
|||||||
defaultValue={coord.x}
|
defaultValue={coord.x}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{hasY && (
|
{showY && (
|
||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
<label className="form-label">Coordenada Y</label>
|
<label className="form-label">Coordenada Y</label>
|
||||||
<input
|
<input
|
||||||
|
|||||||
52
src/components/ModalImport.jsx
Normal file
52
src/components/ModalImport.jsx
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
export default function ModalImport({ show, handleAddCoord, close }) {
|
||||||
|
if (!show) return null;
|
||||||
|
let coord = "";
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="modal"
|
||||||
|
tabIndex="-1"
|
||||||
|
style={{ display: "block", backgroundColor: "rgba(0,0,0,0.3)" }}
|
||||||
|
>
|
||||||
|
<div className="modal-dialog">
|
||||||
|
<div className="modal-content">
|
||||||
|
<div className="modal-header">
|
||||||
|
<h5 className="modal-title">Añadir Coordenadas</h5>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn-close"
|
||||||
|
onClick={() => close(false)}
|
||||||
|
></button>
|
||||||
|
</div>
|
||||||
|
<div className="modal-body">
|
||||||
|
<div className="form-floating mb-3">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="form-control"
|
||||||
|
id="coordInput"
|
||||||
|
placeholder="Coordenadas"
|
||||||
|
onChange={(event) => (coord = event.target.value)}
|
||||||
|
/>
|
||||||
|
<label htmlFor="coordInput">Pega la coord</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="modal-footer d-flex justify-content-between">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-secondary"
|
||||||
|
onClick={() => close(false)}
|
||||||
|
>
|
||||||
|
Close
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-primary"
|
||||||
|
onClick={() => handleAddCoord(coord)}
|
||||||
|
>
|
||||||
|
Guardar Coord
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -6,6 +6,8 @@ import RemoveIcon from "./RemoveIcon";
|
|||||||
import StaticModal from "./StaticModal";
|
import StaticModal from "./StaticModal";
|
||||||
import EditarModal from "./EditarModal";
|
import EditarModal from "./EditarModal";
|
||||||
import TimedToast from "./TimedToast";
|
import TimedToast from "./TimedToast";
|
||||||
|
import BotonAdd from "./BotonAdd";
|
||||||
|
import ModalImport from "./ModalImport";
|
||||||
|
|
||||||
function Modall({ show, CloseModal, Coord, Coords, EliminarCoord, tipo }) {
|
function Modall({ show, CloseModal, Coord, Coords, EliminarCoord, tipo }) {
|
||||||
if (show === true && Coord !== null) {
|
if (show === true && Coord !== null) {
|
||||||
@@ -34,18 +36,40 @@ export default function Keeper({ tipo }) {
|
|||||||
const [showEditar, setEditar] = useState(false);
|
const [showEditar, setEditar] = useState(false);
|
||||||
const [showToast, setShowToast] = useState(false);
|
const [showToast, setShowToast] = useState(false);
|
||||||
const [selCoord, setCoord] = useState(null);
|
const [selCoord, setCoord] = useState(null);
|
||||||
|
const [showImport, setShowImport] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const storedCoords = JSON.parse(localStorage.getItem(tipo) || "[]");
|
const storedCoords = JSON.parse(localStorage.getItem(tipo) || "[]");
|
||||||
|
|
||||||
console.log(storedCoords);
|
|
||||||
if (storedCoords) {
|
if (storedCoords) {
|
||||||
setCoords(storedCoords);
|
setCoords(storedCoords);
|
||||||
}
|
}
|
||||||
}, [tipo]);
|
}, [tipo]);
|
||||||
|
|
||||||
|
const añadirCoord = (coord) => {
|
||||||
|
const regex = /- (.*), X: (-?\d+)(?:\s*Y:\s*(-?\d+))?\s*Z:\s*(-?\d+)/;
|
||||||
|
const match = coord.match(regex);
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
const [_, descripcion, x, y, z] = match;
|
||||||
|
const newCoord = {
|
||||||
|
descripcion,
|
||||||
|
x: parseInt(x),
|
||||||
|
y: y ? parseInt(y) : null,
|
||||||
|
z: parseInt(z),
|
||||||
|
num: coords.length + 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
const newCoords = [...coords, newCoord];
|
||||||
|
setCoords(newCoords);
|
||||||
|
localStorage.setItem(tipo, JSON.stringify(newCoords));
|
||||||
|
setShowToast(true);
|
||||||
|
setShowImport(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handlePaste = async (e) => {
|
const handlePaste = async () => {
|
||||||
const text = await navigator.clipboard.readText();
|
const text = await navigator.clipboard.readText();
|
||||||
const regex = /- (.*), X: (-?\d+)(?:\s*Y:\s*(-?\d+))?\s*Z:\s*(-?\d+)/;
|
const regex = /- (.*), X: (-?\d+)(?:\s*Y:\s*(-?\d+))?\s*Z:\s*(-?\d+)/;
|
||||||
const match = text.match(regex);
|
const match = text.match(regex);
|
||||||
@@ -104,6 +128,15 @@ export default function Keeper({ tipo }) {
|
|||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<div className="d-lg-none">
|
||||||
|
<BotonAdd show={true} setshow={setShowImport} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ModalImport
|
||||||
|
show={showImport}
|
||||||
|
handleAddCoord={añadirCoord}
|
||||||
|
close={setShowImport}
|
||||||
|
/>
|
||||||
<Modall
|
<Modall
|
||||||
show={showModal}
|
show={showModal}
|
||||||
CloseModal={() => setModal(false)}
|
CloseModal={() => setModal(false)}
|
||||||
@@ -112,7 +145,6 @@ export default function Keeper({ tipo }) {
|
|||||||
EliminarCoord={setCoords}
|
EliminarCoord={setCoords}
|
||||||
tipo={tipo}
|
tipo={tipo}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<EditarModal
|
<EditarModal
|
||||||
show={showEditar}
|
show={showEditar}
|
||||||
close={() => setEditar(false)}
|
close={() => setEditar(false)}
|
||||||
@@ -120,14 +152,12 @@ export default function Keeper({ tipo }) {
|
|||||||
coord={selCoord}
|
coord={selCoord}
|
||||||
setCoords={setCoords}
|
setCoords={setCoords}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TimedToast
|
<TimedToast
|
||||||
durationMs={5000}
|
durationMs={5000}
|
||||||
setShow={setShowToast}
|
setShow={setShowToast}
|
||||||
show={showToast}
|
show={showToast}
|
||||||
message={`Copiada Coordenada [${selCoord?.descripcion}]`}
|
message={`Copiada Coordenada [${selCoord?.descripcion}]`}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="accordion" id="accordionNuevaCoord">
|
<div className="accordion" id="accordionNuevaCoord">
|
||||||
<div className="accordion-item">
|
<div className="accordion-item">
|
||||||
<h2 className="accordion-header" id="headingNuevaCoord">
|
<h2 className="accordion-header" id="headingNuevaCoord">
|
||||||
@@ -162,13 +192,11 @@ export default function Keeper({ tipo }) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
{coords.length == 0 && (
|
{coords.length == 0 && (
|
||||||
<h2 className="list-group-item text-center">
|
<h2 className="list-group-item text-center">
|
||||||
No hay Coordenadas que Mostrar.
|
No hay Coordenadas que Mostrar.
|
||||||
</h2>
|
</h2>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<table class="table table-hover table-striped">
|
<table class="table table-hover table-striped">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
Reference in New Issue
Block a user