Absurdo, não é? Eu preciso simular um back-end porque, sendo um desenvolvedor full stack, ainda não criei meu próprio back-end para a minha aplicação. Problemas, não é mesmo?
Devido a essa pequena complicação, eu comecei a adiantar os métodos que, no futuro, seriam responsáveis por fazer as requisições para o back-end. Assim, mesmo sem esses endpoints, eu poderia avançar no desenvolvimento do front-end para depois conectar aos endpoints.
Não é a primeira vez que faço isso, então eu já sabia o que estava fazendo.
Primeiro, aqui está o utilitário que criei:
import generateHashId from './generateHashId';
type localStorageBaseType = {
id: string;
created_at: Date;
};
export class NotFoundError extends Error {
constructor(message: string) {
super(message);
this.message = message;
}
}
export class StorageError extends Error {
constructor(message: string) {
super(message);
this.message = message;
}
}
class LocalStorageUtil<T extends localStorageBaseType> {
private key: string;
constructor(key: string) {
this.key = key;
}
// Obtém os dados do Local Storage para a chave especificada
getData(): T[] {
const data = localStorage.getItem(this.key);
return data ? JSON.parse(data) : [];
}
getById(id: string): T | undefined {
const data = this.getData();
return data.find((item) => item.id === id);
}
// Salva os dados no Local Storage para a chave especificada
saveData(data: T[]): void {
localStorage.setItem(this.key, JSON.stringify(data));
}
updateItem(item: T): void {
const data = this.getData();
const findIndex = data.findIndex((i) => i.id === item.id);
if (findIndex === -1) {
throw new NotFoundError('Item not found');
}
if (findIndex !== -1) {
data[findIndex] = item;
this.saveData(data);
}
}
// Adiciona um novo item aos dados existentes
addItem(item: Omit<T, 'id' | 'created_at'>): void {
if (!item) {
throw new StorageError('data is required');
}
const data = this.getData();
const newItem: T = {
id: generateHashId(16),
created_at: new Date(),
...item
} as T;
data.push(newItem);
this.saveData(data);
}
// Remove um item específico dos dados
removeItem(id: string): void {
const data = this.getData();
const filteredData = data.filter((item) => item.id !== id);
this.saveData(filteredData);
}
// Remove todos os dados relacionados à chave especificada
deleteData(): void {
localStorage.removeItem(this.key);
}
}
export default LocalStorageUtil;
Como pode ver, é uma classe que de dar alguns métodos, os principais de um CRUD. E o uso dela é bem simples, como pode ver, esta usando typescript o que já ajuda bastante.
Primeiro passo: instanciando a casse
Como ela é uma classe, precisamos instanciar ela em algum lugar, ai ficar sua vontade
const keys = {
budgets: '@budgets'
};
export type Budgets = {
name: string;
value: number;
} & localStorageBaseType;
const budgetStorage = new LocalStorageUtil<Budgets>(keys.budgets);
export { budgetStorage };
O que é esse localStorageBaseType? é somente um tipo base para você da merge com o tipo que vc quer passar para a classe, ela vai usar para ajudar na tipagem dos metodos.
ela por baixo dos planos tem id e um created_at para ajudar nos métodos da classe de buscar e update.
Segundo passo: finalmente usando
O uso ficar bem fácil, é so pegar budgetStorage e começar usar os métodos.
budgetStorage.addItem({
name: 'Salário',
value: 1000
});
const budgets = budgetStorage.getData()
// spec: {
// name: 'Salário',
// value: 1000
// id: 'x1y2z3',
// created_at: '17/12/2023'
// }
budgetStorage.updateItem({
name: 'Salário',
id: 'x1y2z3',
value: 2000,
created_at: new Date()
});
// Para atualizar é so passar o item com o update que o
// metodo vai buscar pelo id para atualizar o item
Os outros métodos são bem fáceis de usar e com a ajuda o typescript, temos o removeItem, deleteData, getById.
lembrando que foi uma solução bem simples para ajudar a completar um etapa do projeto e claro que da pra melhorar. é isso.
Top comments (0)