Skip to content

Commit dcf1f3f

Browse files
Merge pull request #542 from kevinalfito69/main
Contact Apps React JS
2 parents 94f3e0f + 976536b commit dcf1f3f

28 files changed

+27732
-0
lines changed

contacts-app/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Contact app react
2+
3+
this repo is made to learn react fundamentals, and react router.
4+
## feature
5+
6+
<ul>
7+
<li>Add contact</li>
8+
<li>Delete contact</li>
9+
</ul>

contacts-app/package-lock.json

Lines changed: 26671 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

contacts-app/package.json

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"name": "react-starter-project",
3+
"version": "1.0.0",
4+
"description": "",
5+
"main": "index.js",
6+
"scripts": {
7+
"start": "react-scripts start",
8+
"build": "react-scripts build",
9+
"test": "react-scripts test --env=jsdom",
10+
"eject": "react-scripts eject"
11+
},
12+
"browserslist": [
13+
">0.2%",
14+
"not dead",
15+
"not ie <= 11",
16+
"not op_mini all"
17+
],
18+
"keywords": [],
19+
"author": "",
20+
"license": "ISC",
21+
"dependencies": {
22+
"prop-types": "^15.8.1",
23+
"react": "^18.0.0",
24+
"react-dom": "^18.0.0",
25+
"react-icons": "^4.4.0",
26+
"react-router-dom": "^6.4.1",
27+
"react-scripts": "^5.0.1"
28+
}
29+
}
4.48 KB
Loading
2.21 KB
Loading
14.9 KB
Loading
13.4 KB
Loading

contacts-app/public/index.html

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<!DOCTYPE html>
2+
<html lang="id">
3+
<head>
4+
<meta charset="utf-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<!-- START: Google Font -->
7+
<link rel="preconnect" href="https://fonts.googleapis.com">
8+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
9+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;700&display=swap" rel="stylesheet">
10+
<!-- END: Google Font -->
11+
<title>Contact Apps</title>
12+
</head>
13+
<body>
14+
<div id="root"></div>
15+
</body>
16+
</html>
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
import React from "react";
2+
import { Route, Routes } from "react-router-dom";
3+
import Navigation from "./Navigation";
4+
import HomePage from "../pages/HomePage";
5+
import AddPage from "../pages/AddPage";
6+
import RegisterPage from "../pages/RegisterPage";
7+
import LoginPage from "../pages/LoginPage";
8+
import { putAccessToken, getUserLogged } from "../utils/api";
9+
import { LocaleProvider } from "../contexts/LocaleContext";
10+
class ContactApp extends React.Component {
11+
constructor(props) {
12+
super(props);
13+
this.state = {
14+
authedUser: null,
15+
initializing: true,
16+
localeContext: {
17+
locale: localStorage.getItem("locale") || "id",
18+
localeToggle: () => {
19+
this.setState((prevState) => {
20+
const newLocale =
21+
prevState.localeContext.locale === "id"
22+
? "en"
23+
: "id";
24+
localStorage.setItem("locale", newLocale);
25+
return {
26+
localeContext: {
27+
...prevState.localeContext,
28+
// jika locale context sama dengan id maka ubah menjadi eng
29+
locale: newLocale,
30+
},
31+
};
32+
});
33+
},
34+
},
35+
};
36+
this.onLoginSuccess = this.onLoginSuccess.bind(this);
37+
this.onLogout = this.onLogout.bind(this);
38+
}
39+
40+
async componentDidMount() {
41+
const { data } = await getUserLogged();
42+
43+
this.setState(() => {
44+
return {
45+
authedUser: data,
46+
initializing: false,
47+
};
48+
});
49+
}
50+
onLogout() {
51+
this.setState(() => {
52+
return {
53+
authedUser: null,
54+
};
55+
});
56+
putAccessToken("");
57+
}
58+
59+
async onLoginSuccess({ accessToken }) {
60+
putAccessToken(accessToken);
61+
const { data } = await getUserLogged();
62+
this.setState(() => {
63+
return {
64+
authedUser: data,
65+
};
66+
});
67+
}
68+
69+
render() {
70+
if (this.state.initializing) {
71+
return null;
72+
}
73+
if (this.state.authedUser == null) {
74+
return (
75+
<LocaleProvider value={this.state.localeContext}>
76+
<div className="contact-app">
77+
<header className="contact-app__header">
78+
<h1>Aplikasi Kontak</h1>
79+
</header>
80+
<main>
81+
<Routes>
82+
<Route
83+
path="/*"
84+
element={
85+
<LoginPage
86+
loginSuccess={this.onLoginSuccess}
87+
/>
88+
}
89+
/>
90+
<Route
91+
path="/register"
92+
element={<RegisterPage />}
93+
/>
94+
</Routes>
95+
</main>
96+
</div>
97+
</LocaleProvider>
98+
);
99+
}
100+
101+
return (
102+
<LocaleProvider value={this.state.localeContext}>
103+
<div className="contact-app">
104+
<header className="contact-app__header">
105+
<h1>
106+
{this.state.localeContext.locale === "id"
107+
? "Aplikasi kontak"
108+
: "Contact App"}
109+
</h1>
110+
<Navigation
111+
logout={this.onLogout}
112+
name={this.state.authedUser.name}
113+
/>
114+
</header>
115+
<main>
116+
<Routes>
117+
<Route path="/" element={<HomePage />} />
118+
<Route path="/add" element={<AddPage />} />
119+
</Routes>
120+
</main>
121+
</div>
122+
</LocaleProvider>
123+
);
124+
}
125+
}
126+
export default ContactApp;
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import React from "react";
2+
import PropTypes from "prop-types";
3+
class ContactInput extends React.Component {
4+
constructor(props) {
5+
super(props);
6+
7+
// inisialisasi state
8+
this.state = {
9+
name: "",
10+
tag: "",
11+
};
12+
13+
this.onNameChangeEventHandler = this.onNameChangeEventHandler.bind(this);
14+
this.onTagChangeEventHandler = this.onTagChangeEventHandler.bind(this);
15+
this.onSubmitEventHandler = this.onSubmitEventHandler.bind(this);
16+
}
17+
18+
onNameChangeEventHandler(event) {
19+
this.setState(() => {
20+
return {
21+
name: event.target.value,
22+
};
23+
});
24+
}
25+
26+
onTagChangeEventHandler(event) {
27+
this.setState(() => {
28+
return {
29+
tag: event.target.value,
30+
};
31+
});
32+
}
33+
34+
onSubmitEventHandler(event) {
35+
event.preventDefault();
36+
this.props.addContact(this.state);
37+
}
38+
39+
render() {
40+
return (
41+
<form className="contact-input" onSubmit={this.onSubmitEventHandler}>
42+
<input type="text" placeholder="Nama" value={this.state.name} onChange={this.onNameChangeEventHandler} />
43+
<input type="text" placeholder="Tag" value={this.state.tag} onChange={this.onTagChangeEventHandler} />
44+
<button type="submit">Tambah</button>
45+
</form>
46+
);
47+
}
48+
}
49+
ContactInput.propTypes = {
50+
addContact: PropTypes.func.isRequired,
51+
};
52+
53+
export default ContactInput;

0 commit comments

Comments
 (0)