Skip to content

Instantly share code, notes, and snippets.

@mugan86
Last active November 12, 2023 09:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mugan86/57c39943dbdf6f44b00de65532f5f95c to your computer and use it in GitHub Desktop.
Save mugan86/57c39943dbdf6f44b00de65532f5f95c to your computer and use it in GitHub Desktop.
Bookmark Project
import { $, useSignal, useStore, useVisibleTask$} from "@builder.io/qwik";
export function useLocalStorage(key: string, loadingValue: boolean = true) {
const data = useStore<{key: string, value: any[]}>({
key,
value: []
});
const loading = useSignal(loadingValue);
useVisibleTask$(() => {
const localData = localStorage.getItem(data.key) as any;
if (localData) {
data.value = JSON.parse(localData);
}
loading.value = false;
});
const set = $(async(saveData: any) => {
data.value = saveData;
localStorage.setItem(data.key, JSON.stringify(saveData));
});
const get = $(() => {
return data.value;
});
const clear = $((initValue = []) => {
data.value = initValue;
data.key = key;
localStorage.removeItem(data.key);
});
return {
set,
get,
clear,
data,
loading
};
}
.form {
display: flex;
flex-direction: column;
gap: 10px;
max-width: 350px;
background-color: #fff;
padding: 20px;
border-radius: 20px;
position: relative;
}
.title {
font-size: 28px;
color: royalblue;
font-weight: 600;
letter-spacing: -1px;
position: relative;
display: flex;
align-items: center;
padding-left: 30px;
}
.title::before,
.title::after {
position: absolute;
content: "";
height: 16px;
width: 16px;
border-radius: 50%;
left: 0px;
background-color: royalblue;
}
.title::before {
width: 18px;
height: 18px;
background-color: royalblue;
}
.title::after {
width: 18px;
height: 18px;
animation: pulse 1s linear infinite;
}
.message,
.signin {
color: rgba(88, 87, 87, 0.822);
font-size: 14px;
}
.signin {
text-align: center;
}
.signin a {
color: royalblue;
}
.signin a:hover {
text-decoration: underline royalblue;
}
.flex {
display: flex;
width: 100%;
gap: 6px;
}
.form label {
position: relative;
}
.form label .input {
width: 100%;
padding: 10px 10px 20px 10px;
outline: 0;
border: 1px solid rgba(105, 105, 105, 0.397);
border-radius: 10px;
}
.form label .input+span {
position: absolute;
left: 10px;
top: 28px;
color: grey;
font-size: 0.9em;
cursor: text;
transition: 0.3s ease;
}
.form label .input:placeholder-shown+span {
top: 20px;
font-size: 0.9em;
}
.form label .input:focus+span,
.form label .input:valid+span {
top: 0px;
font-size: 0.7em;
font-weight: 600;
}
.form label .input:valid+span {
color: green;
}
span.invalid-class {
color: red !important;
}
.invalid-message {
background-color: rgb(244, 165, 165);
margin-top: -0.3rem;
padding: 1rem;
border-radius: 0.5rem;
}
input.input {
margin-top: 15px;
}
.submit {
border: none;
outline: none;
background-color: royalblue;
padding: 10px;
border-radius: 10px;
color: #fff;
font-size: 16px;
transform: .3s ease;
}
.submit:hover {
background-color: rgb(56, 90, 194);
cursor: pointer;
}
@keyframes pulse {
from {
transform: scale(0.9);
opacity: 1;
}
to {
transform: scale(1.8);
opacity: 0;
}
}
.checkbox {
appearance: none;
width: 20px;
height: 20px;
border: 2px solid rgb(56, 90, 194);
border-radius: 5px;
background-color: transparent;
display: inline-block;
position: relative;
margin-right: 10px;
cursor: pointer;
}
.checkbox:before {
content: "";
background-color: rgb(56, 90, 194);
display: block;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) scale(0);
width: 10px;
height: 10px;
border-radius: 3px;
transition: all 0.3s ease-in-out;
}
.checkbox:checked:before {
transform: translate(-50%, -50%) scale(1);
}
.checkbox-label {
font-size: 18px;
cursor: pointer;
color: grey;
user-select: none;
display: flex;
align-items: center;
}
import { component$, useStyles$ } from '@builder.io/qwik';
import { Form, type DocumentHead, routeAction$ } from '@builder.io/qwik-city';
import styles from './index.css?inline';
export const useAddUrlToStoreInLocal = routeAction$(async (data) => {
// Para ver en consola como coge los datos
console.log('Title', data.title);
console.log('Description', data.description);
console.log('URL', data.url);
return {
success: true,
data,
};
});
export default component$(() => {
useStyles$(styles);
const action = useAddUrlToStoreInLocal();
return (
<div>
<h1>
Repositorio de Marcadores Favoritos <span class="lightning">⚡️</span>
</h1>
<div>
<Form class="form" action={action}>
<p class="title">Añadir un nuevo enlace </p>
<p class="message">Añadir enlace para almacenarlo como marcador</p>
<label>
<input class="input" type="text" name="title" />
<span>Título</span>
</label>
<label>
<input class="input" type="text" name="description" />
<span>Descripción</span>
</label>
<label>
<input class="input" type="text" name="url" />
<span>Enlace</span>
</label>
<button class="submit">Guardar</button>
</Form>
</div>
</div>
);
});
export const head: DocumentHead = {
title: 'Qwik Book - BookmarkDB',
meta: [
{
name: 'description',
content:
'Proyecto trabajando con formularios donde implementamos un sistema para almacenar enlaces favoritos en local',
},
{
name: 'keywords',
content: 'qwik, qwik-book, forms, zod, bookmark',
},
{
name: 'author',
content: 'Anartz Mugika Ledo',
},
{
name: 'og:image',
content:
'https://jgengle.github.io/Leaflet/examples/quick-start/thumbnail.png',
},
{
name: 'og:url',
content: 'https://github.com/qwik-book/qwik-book-projects',
},
{
name: 'twitter:image',
content:
'https://jgengle.github.io/Leaflet/examples/quick-start/thumbnail.png',
},
{
name: 'twitter:card',
content: 'summary_large_image',
},
{
name: 'twitter:title',
content: 'Qwik - El libro - Proyecto BookmarkDB',
},
{
name: 'twitter:description',
content:
'Proyecto trabajando con formularios donde implementamos un sistema para almacenar enlaces favoritos en local',
},
],
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment