Skip to content

Commit

Permalink
Merge pull request #15 from blessenm/14/typescript-v2
Browse files Browse the repository at this point in the history
Converts all files to typescript
  • Loading branch information
Blessan Mathew authored Feb 17, 2020
2 parents 825d46d + cd9e90c commit 3839ec6
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 49 deletions.
31 changes: 18 additions & 13 deletions src/components/Add.jsx → src/components/Add.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import React from "react";

import useForm from "../hooks/useForm";
import useFirebase from "../hooks/useFirebase";
import useForm, { InputInterface, ActionInterface } from "../hooks/useForm";
import useFirebase, { WordInterface } from "../hooks/useFirebase";

interface PropsInterface {
onAdd: Function;
}

const INITIAL_STATE = [
{
name: "type",
type: "select",
type: "select" as const,
value: "",
placeholder: "Type",
required: true,
options: [
Expand All @@ -19,7 +24,7 @@ const INITIAL_STATE = [
},
{
name: "article",
type: "select",
type: "select" as const,
value: "",
required: true,
options: [
Expand All @@ -33,26 +38,26 @@ const INITIAL_STATE = [
{
name: "word",
placeholder: "Word",
type: "text",
type: "text" as const,
value: "",
required: true
},
{
name: "meaning",
placeholder: "Meaning",
type: "text",
type: "text" as const,
value: "",
required: true
},
{
name: "note",
placeholder: "Note",
type: "text",
type: "text" as const,
value: ""
}
];

function reducer(state, action) {
function reducer(state: InputInterface[], action: ActionInterface) {
const { type, name, value } = action;

if (type === "edit" && name === "type") {
Expand All @@ -77,11 +82,11 @@ function reducer(state, action) {
return state;
}

function validator(inputs) {
function validator(inputs: InputInterface[]) {
const inputMap = inputs.reduce((map, input) => {
map[input.name] = input;
return map;
}, {});
}, {} as { [key: string]: InputInterface });

const requiredInputs = !inputs.some(input => {
if (input.required && !input.value) {
Expand All @@ -103,7 +108,7 @@ function validator(inputs) {
}
}

function Add({ onAdd }) {
function Add({ onAdd }: PropsInterface) {
const { state, isValid, change, reset } = useForm(INITIAL_STATE, {
reducer,
validator
Expand All @@ -116,7 +121,7 @@ function Add({ onAdd }) {
...prev,
[property.name]: property.value
};
}, {});
}, {} as WordInterface);
addWordToFirebase(word).then(() => {
reset();
onAdd();
Expand All @@ -135,7 +140,7 @@ function Add({ onAdd }) {
onChange={change}
disabled={input.disabled}
>
{input.options.map(option => (
{input.options?.map(option => (
<option key={option.value} value={option.value}>
{option.label}
</option>
Expand Down
12 changes: 8 additions & 4 deletions src/components/App.jsx → src/components/App.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
import React, { useState, useEffect } from "react";
import "./App.css";

import useFirebase from "../hooks/useFirebase";
import useFirebase, { WordInterface } from "../hooks/useFirebase";

import Login from "./Login";
import Add from "./Add";
import View from "./View";

interface Global {
logout?: Function;
}

function App() {
const [words, setWords] = useState([]);
const [words, setWords] = useState<WordInterface[]>([]);
const { user, getAllWords, logout } = useFirebase();
window.logout = logout;
(window as Global).logout = logout;

const getWords = () => {
getAllWords().then(setWords);
getAllWords().then(words => words && setWords(words));
};

useEffect(getWords, [getAllWords]);
Expand Down
6 changes: 3 additions & 3 deletions src/components/Login.jsx → src/components/Login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ import useFirebase from "../hooks/useFirebase";
const INITIAL_STATE = [
{
placeholder: "Email",
type: "email",
type: "email" as const,
name: "email",
value: "[email protected]",
required: true
},
{
placeholder: "Password",
type: "password",
type: "password" as const,
name: "password",
value: "",
required: true
Expand All @@ -30,7 +30,7 @@ function Login() {
...prev,
[property.name]: property.value
};
}, {});
}, {} as { email: string; password: string });
loginToFirebase(email, password);
reset();
};
Expand Down
7 changes: 6 additions & 1 deletion src/components/View.jsx → src/components/View.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import React from "react";
import { WordInterface } from "../hooks/useFirebase";

function View({ words = [] }) {
interface PropsInterface {
words: WordInterface[];
}

function View({ words = [] }: PropsInterface) {
return (
<section className="wb-view">
{words.map(({ word, article, meaning, note, type }, index) => (
Expand Down
47 changes: 31 additions & 16 deletions src/hooks/useFirebase.js → src/hooks/useFirebase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@ import * as firebase from "firebase/app";
import "firebase/auth";
import "firebase/firestore";

export interface WordInterface {
article: string;
meaning: string;
note: string;
timestamp: firebase.firestore.Timestamp;
type: string;
word: string;
}

const firebaseConfig = {
apiKey: "AIzaSyAWznMXfEF-FMt9OUT10Twzxr382zfs3MU",
authDomain: "mein-woerterbuch.firebaseapp.com",
Expand All @@ -14,7 +23,7 @@ const firebaseConfig = {
measurementId: "G-06SEN5MFN2"
};

function loginToFirebase(email, password) {
function loginToFirebase(email: string, password: string): void {
firebase
.auth()
.signInWithEmailAndPassword(email, password)
Expand All @@ -34,47 +43,53 @@ function logout() {
firebase.auth().signOut();
}

function addWordToFirebase(word) {
function addWordToFirebase(word: WordInterface): Promise<string | Error> {
word.timestamp = firebase.firestore.Timestamp.now();

return firebase
.firestore()
.collection("woerte")
.add(word)
.then(function(docRef) {
console.log("Document written with ID: ", docRef.id);
const result = `Document written with ID: ${docRef.id}`;
console.log(result);
return result;
})
.catch(function(error) {
console.error("Error adding document: ", error);
const result = `Error adding document: ${error}`;
console.error(result);
return result;
});
}

function getAllWords() {
function getAllWords(): Promise<WordInterface[] | void> {
return firebase
.firestore()
.collection("woerte")
.orderBy("timestamp", "desc")
.get()
.then(snapshot => {
const words = [];
snapshot.forEach(doc => words.push(doc.data()));
const words: WordInterface[] = [];
snapshot.forEach(doc => words.push(doc.data() as WordInterface));
return words;
})
.catch(err => console.log(err));
.catch(error => {
console.log(error);
});
}

let firbaseAuthStateListener;

function useFirebase() {
const [user, setUser] = useState(null);
const [user, setUser] = useState<firebase.User | null>(null);

!firebase.apps.length && firebase.initializeApp(firebaseConfig);

useEffect(() => {
firbaseAuthStateListener = firebase.auth().onAuthStateChanged(setUser);

return () => firbaseAuthStateListener();
}, []);
useEffect(
() =>
firebase.auth().onAuthStateChanged(user => {
user && setUser(user);
}),
[]
);

return {
user,
Expand Down
32 changes: 20 additions & 12 deletions src/hooks/useForm.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,40 @@
import { useReducer, ChangeEvent } from "react";
import { useReducer, ChangeEventHandler, ChangeEvent } from "react";

interface Input {
export interface InputInterface {
name: string;
type: string;
type: "text" | "password" | "email" | "select";
placeholder?: string;
required?: boolean;
disabled?: boolean;
options?: Array<{ label: string; value: string }>;
value: string;
}

interface Options {
interface OptionsInterface {
reducer?: Function;
validator?: Function;
}

interface State {
state: Array<Input>;
interface FormInterface {
state: InputInterface[];
isValid: boolean;
change: Function;
change: ChangeEventHandler;
reset: Function;
}

interface Action {
export interface ActionInterface {
type: string;
name?: string;
value?: string;
}

function useForm(inputs: Array<Input>, options: Options = {}): State {
function change(evt: ChangeEvent<HTMLInputElement | HTMLSelectElement>) {
function useForm(
inputs: InputInterface[],
options: OptionsInterface = {}
): FormInterface {
function change(
evt: ChangeEvent<HTMLInputElement | HTMLSelectElement>
): void {
const {
target: { name, value }
} = evt;
Expand All @@ -40,7 +45,7 @@ function useForm(inputs: Array<Input>, options: Options = {}): State {
dispatch({ type: "reset" });
}

function validator(inputs: Array<Input>) {
function validator(inputs: InputInterface[]) {
return !inputs.some(input => {
if (input.required && !input.value) {
return true;
Expand All @@ -50,7 +55,10 @@ function useForm(inputs: Array<Input>, options: Options = {}): State {
});
}

function reducer(state: State, action: Action): State {
function reducer(
state: FormInterface,
action: ActionInterface
): FormInterface {
const { state: inputs } = state;
const { type, name, value } = action;

Expand Down

0 comments on commit 3839ec6

Please sign in to comment.