[WIL 6週間]航海99組プロジェクト愛犬動物病院予約プラットフォームwith reaction
14484 ワード
今回の航行996週目は初めて反応器を使ったチームミニプロジェクトを試みました!
ついに、私の好きなフィードバックを利用して、バックグラウンドの開発者と初めてチームで協力して、とても楽しかったです.
プロジェクト期間:2021-07-09~2012-07-15
項目名称:アプギ盟(愛犬動物病院予約プラットフォーム)
チームメンバー:反応開発者3名、スプリングガイド開発者2名
使用テクニック:反応器、火ベース、スプリングガイド
IDE:VSコードの使用
項目説明:受診する症状の種類を選んだ後、専門病院のために予約システムを構築する
機能:会員登録と登録、個人情報画像アップロード、病院予約と評論採点システム、私の個人ホームページ上の予約履歴を表示し、受診したい症状病種別をスクリーニングする
プロジェクト進捗:プロジェクトテーマの選択->ワイヤフレーム->必要な機能の選択->必要な機能のオンデマンドapi整理(URLとパラメータ名)->フロントエンドとバックエンド開発者が分担->機能実装->機能テスト
ワイヤフレームurl-https://ovenapp.io/view/gMfUj8EvR4DBv1FG6g5BwpVkd6ur0LrA#sNWSj
notion url - https://www.notion.so/26-ac379cabede94755ae8303bba6f9361c
1.ネットワークにログインしたときにサーバからランダムトークン値を取得し、axiosヘッダファイルとWebサービスクッキーに格納し、jwt方式でサーバと通信するログイン時にユーザのアイデンティティとパスワードをパラメータとしてサーバに送信し、サーバはランダムなトークン値(ユーザがDBに存在する場合)に応答する.応答値としてデータを送信->クライアントがトークン値を受信し、axiosのヘッダファイルにデフォルトの許可転送値を設定->tokenというクッキーを実行してトークン値を格納->通常処理後、ホームページ に移動する
1.データベースに格納されている病院ディレクトリの出力 aixosをインスタンス化し、通信後getHospitalsというレプリケーション動作関数を使用して病院リストをレプリケーション状態値に保存し、map関数を使用してクライアント出力 を行う.
1.当該病院のid値を調べた後、該当病院の詳細情報を出力する useParams()を使用してurlパラメータ値を取得->useEffectを使用して初期レンダリング時のgetHospitaldB関数に対応するid値を入れてreduce action関数を呼び出す->reduce状態値に病院詳細データを格納する 2.病院のコメントリスト UseParams()を使用してurlパラメータ値を取得する->Effectを使用して初期レンダリング時のgetReviewDB関数に対応するid値を入れてReduct action関数を呼び出す->Reduct状態値に対応する病院レポートデータ を格納する
3.コメントの作成 handleAddReview関数では、コメントスコアとコンテンツをパラメータ->axios postメソッドにコメントID、スコアとコンテンツ->getReviewDB実行後にステータス値反映を再適用する に送信します.地図を使用して病院の位置を検索する リッドス状態値から病院の住所を読み込み、KACA APIを使用して地図にマークする住所 を挿入する.
1.カテゴリをクリックすると、そのカテゴリの専門知識を持つ病院のリストが表示されますカテゴリをクリックすると、クリックしたカテゴリがChangeColor関数を使用してシェーディングされます. 該当カテゴリキーワードを符号化し、サーバに送信後にデータを受信し、Dateを設定後に病院リスト を出力する.
1.ペットの犬の名前、予約日程と要求事項を記入した後、予約をクリックして病院の予約を完了する
「予定」をクリックしてreserve関数を実行する->予定情報を変数として、addReservationDB reduce関数を実行する->データベースに予定履歴を保存する
1.プロファイル画像の変更カメラボタンをクリックしてSelectFile関数を実行して写真をアップロードすると、画像がプレビュー形式で出力されます->右クリックアップロードFB実行->画像ファイルが火庫に保存されます->保存が完了したら、画像URLを受信してそのURLをステータス値->/userinfo/imageapiに保存します.Devieのプロファイルイメージの更新->プロファイルイメージのurlをredususer状態値 に更新する
2.ログアウトログアウトボタンをクリックしてlogoutDB関数を実行する->jwtトークン値を保存するトークンcookieを削除->axiosヘッダ値nullに変更->ホームページ に移動
初めて反応器を使ってバックエンドと協力したのは、有意義な時間だったようだ.協力の過程で一般個人のプロジェクトとは違ってコミュニケーションが重要だと感じました.お互いが望む計画の方向性に合意することも重要であり、api設計など多くの面で合意する必要がある.この過程で、誰かが利己的になったり、背いたりすると、プロジェクトは山になるかもしれません.ある部分に困難があれば、なぜ困難があるのかを盲目的に強要するのではなく、理解して解決する能力を持つべきだ.
いったん会社に入ったら、開発は絶対に一人でやるものではありません.チームパートナーがいて、コミュニケーションは開発者が避けられない重要な宿命です.個人の開発力を増やすことも重要だが、残りの99の航海隊プロジェクトの中で、このコミュニケーション能力を育成する時間が増えることを望んでいる.
ワイヤフレーム-https://ovenapp.io/view/gMfUj8EvR4DBv1FG6g5BwpVkd6ur0LrA#sNWSj
コンセプト企画-https://www.notion.so/26-ac379cabede94755ae8303bba6f9361c
github - https://github.com/Sparta-MungMung/mungmung_client
インプリメンテーションドメイン-http://munghospital.shop/
プロジェクト概要YouTube url-https://www.youtube.com/watch?v=Sd98UjrPmB4
ついに、私の好きなフィードバックを利用して、バックグラウンドの開発者と初めてチームで協力して、とても楽しかったです.
プロジェクトの説明
プロジェクト期間:2021-07-09~2012-07-15
項目名称:アプギ盟(愛犬動物病院予約プラットフォーム)
チームメンバー:反応開発者3名、スプリングガイド開発者2名
使用テクニック:反応器、火ベース、スプリングガイド
IDE:VSコードの使用
項目説明:受診する症状の種類を選んだ後、専門病院のために予約システムを構築する
機能:会員登録と登録、個人情報画像アップロード、病院予約と評論採点システム、私の個人ホームページ上の予約履歴を表示し、受診したい症状病種別をスクリーニングする
プロジェクト進捗:プロジェクトテーマの選択->ワイヤフレーム->必要な機能の選択->必要な機能のオンデマンドapi整理(URLとパラメータ名)->フロントエンドとバックエンド開発者が分担->機能実装->機能テスト
ワイヤフレームurl-https://ovenapp.io/view/gMfUj8EvR4DBv1FG6g5BwpVkd6ur0LrA#sNWSj
notion url - https://www.notion.so/26-ac379cabede94755ae8303bba6f9361c
プロジェクト成果物
ログインと登録のコスト
1.ネットワークにログインしたときにサーバからランダムトークン値を取得し、axiosヘッダファイルとWebサービスクッキーに格納し、jwt方式でサーバと通信する
const loginDB = (userName, password) => {
return function (dispatch, getState, { history }) {
let login_info = {
userName,
password,
};
instance
.post("/user", login_info)
.then((response) => {
console.log(response);
const accessToken = response.data;
// API 요청하는 콜마다 해더에 accessTocken 담아 보내도록 설정
instance.defaults.headers.common["Authorization"] = `${accessToken}`;
//받은 token 쿠키에 저장
setCookie("token", accessToken, 1, "/");
// const token = getCookie("token");
dispatch(setUser(login_info));
history.push("/pages/mainpage");
})
.catch((error) => console.log("로그인 중 에러가 발생했어요!", error));
};
};
コードの説明
ホームページ(病院のリストを表示)
1.データベースに格納されている病院ディレクトリの出力
const getHospitalsDB = () => {
return function (dispatch, getState, { history }) {
instance.get("/hospitals").then((result) => {
dispatch(getHospitals(result.data));
});
};
};
const getHospitals = createAction(GET_HOSPITALS, (hospitals) => ({
hospitals,
}));
export default handleActions(
{
[GET_HOSPITALS]: (state, action) => {
return produce(state, (draft) => {
draft.hospital_list = action.payload.hospitals;
});
},
},
initialState
);
コードの説明
病院の詳細ページ
1.当該病院のid値を調べた後、該当病院の詳細情報を出力する
const { id } = useParams();
useEffect(() => {
dispatch(userActions.loginCheckDB());
dispatch(getHospitalDB(id));
if (location.state !== undefined) {
setTabIndex(location.state.tabIndex);
}
}, []);
export const getHospitalDB = (id) => {
return function (dispatch, getState, { history }) {
const token = getCookie("token");
instance.defaults.headers.common["Authorization"] = `${token}`;
instance.get(`/hospitals/${id}`).then((result) => {
dispatch(getHospital(result.data));
});
};
};
const getHospital = createAction(GET_HOSPITAL, (hospital) => ({ hospital }));
export default handleActions(
{
[GET_HOSPITAL]: (state, action) =>
produce(state, (draft) => {
draft.hospital = action.payload.hospital;
}),
},
initialState
);
const hospital = useSelector((state) => state.hospital.hospital);
コードの説明
const { id } = useParams();
useEffect(() => {
dispatch(actionCreators.getReviewDB(id));
}, []);
const getReviewDB = (id) => {
return function (dispatch, getState, { history }) {
const token = getCookie("token");
instance.defaults.headers.common["Authorization"] = `${token}`;
instance.get(`/hospitals/${id}/reviews`).then((result) => {
dispatch(getReview(result.data));
});
};
};
const getReview = createAction(GET_REVIEW, (review) => ({ review }));
export default handleActions(
{
[GET_REVIEW]: (state, action) => {
return produce(state, (draft) => {
draft.review_list = action.payload.review;
});
},
},
initialState
);
コードの説明
3.コメントの作成
const handleAddReview = (review) => {
dispatch(actionCreators.addReviewDB(id, review));
};
const addReviewDB = (id, review) => {
return function (dispatch, getState, { history }) {
const token = getCookie("token");
instance.defaults.headers.common["Authorization"] = `${token}`;
const { reviewContent, hospitalRate } = review;
const new_review = {
reviewContent,
hospitalRate,
};
instance.post(`/hospitals/${id}/reviews`, new_review).then((result) => {
dispatch(getReviewDB(id));
});
};
};
コードの説明
const { kakao } = window;
const hospital = useSelector((state) => state.hospital.hospital);
const { hospitalName, hospitalLocation, hospitalNumber } = hospital;
useEffect(() => {
const mapContainer = document.getElementById("myMap"), // 지도를 표시할 div
mapOption = {
center: new kakao.maps.LatLng(33.450701, 126.570667), // 지도의 중심좌표
level: 3, // 지도의 확대 레벨
};
// 지도를 생성합니다
const map = new kakao.maps.Map(mapContainer, mapOption);
// 주소-좌표 변환 객체를 생성합니다
const geocoder = new kakao.maps.services.Geocoder();
// 주소로 좌표를 검색합니다
geocoder.addressSearch(hospitalLocation, function (result, status) {
// 정상적으로 검색이 완료됐으면
if (status === kakao.maps.services.Status.OK) {
const coords = new kakao.maps.LatLng(result[0].y, result[0].x);
// 결과값으로 받은 위치를 마커로 표시합니다
const marker = new kakao.maps.Marker({
map: map,
position: coords,
});
// 인포윈도우로 장소에 대한 설명을 표시합니다
const infowindow = new kakao.maps.InfoWindow({
content: `<div style="width:150px;text-align:center;padding:6px 0;">${hospitalName}</div>`,
});
infowindow.open(map, marker);
// 지도의 중심을 결과값으로 받은 위치로 이동시킵니다
map.setCenter(coords);
}
});
}, []);
コードの説明
診察別フィルタページ
1.カテゴリをクリックすると、そのカテゴリの専門知識を持つ病院のリストが表示されます
const search = (e, idx) => {
changeColor(e, idx);
const keyword = e.target.textContent;
// 한글로 보내면 에러나기때문에 인코딩 후 서버에서 디코딩 진행
const encode = encodeURIComponent(keyword);
instance.get(`/hospitals/search?subject=${encode}`).then((response) => {
setData(response.data);
console.log(response.data);
});
};
コードの説明
予約ページ
1.ペットの犬の名前、予約日程と要求事項を記入した後、予約をクリックして病院の予約を完了する
const reservate = () => {
dispatch(
reservationActions.addReservationDB(id, dogName, schedule, request)
);
};
const addReservationDB = (
hospitalId,
dogName,
reservationDate,
reservationDetail
) => {
return function (dispatch, getState, { history }) {
let new_reservation = {
hospitalId,
dogName,
reservationDate,
reservationDetail,
};
const token = getCookie("token");
instance.defaults.headers.common["Authorization"] = `${token}`;
instance
.post(
"/reservations",
new_reservation
// ... add other header lines like: 'Content-Type': 'application/json'
)
.then((response) => {
console.log(response);
switch (response.data.msg) {
case "success":
dispatch(addReservation(new_reservation));
window.alert(
"예약이 완료되었습니다. 마이페이지에서 예약 목록을 확인해 보세요 :)"
);
history.push("/pages/mypage");
break;
case "not_login":
window.alert("로그인이 필요합니다!");
history.replace("/login");
break;
default:
// window.alert("예약 신청 중 오류가 생겼네요! 다시 부탁드려요!");
dispatch(addReservation(new_reservation));
window.alert("예약이 완료되었습니다.");
history.push("/pages/mypage");
break;
}
})
.catch((error) => {
console.log("예약 저장 중 오류 발생!", error);
});
};
};
コードの説明
「予定
マイページ
1.プロファイル画像の変更
const selectFile = (e) => {
const reader = new FileReader();
const file = imageInput.current.files[0];
reader.readAsDataURL(file);
reader.onloadend = () => {
setPreview(reader.result);
};
};
const uploadFB = () => {
let image = imageInput.current.files[0];
dispatch(imageActions.uploadImageFB(image));
setTimeout(() => setDone(true), 500);
setTimeout(() => setDone(false), 3000);
};
const uploadImageFB = (image) => {
return function (dispatch, getState, { history }) {
const _upload = storage.ref(`images/${image.name}`).put(image);
_upload.then((snapshot) => {
console.log(snapshot);
snapshot.ref.getDownloadURL().then((url) => {
dispatch(uploadImage(url));
instance.post("/userinfo/image", { dogImage: url }).then((response) => {
dispatch(userActions.editUser(url));
});
});
});
};
};
コードの説明
2.ログアウト
const logoutDB = () => {
return function (dispatch, getState, { history }) {
deleteCookie("token");
instance.defaults.headers.common["Authorization"] = null;
delete instance.defaults.headers.common["Authorization"];
dispatch(logout());
history.push("/pages/mainpage");
};
};
コードの説明
に感銘を与える
初めて反応器を使ってバックエンドと協力したのは、有意義な時間だったようだ.協力の過程で一般個人のプロジェクトとは違ってコミュニケーションが重要だと感じました.お互いが望む計画の方向性に合意することも重要であり、api設計など多くの面で合意する必要がある.この過程で、誰かが利己的になったり、背いたりすると、プロジェクトは山になるかもしれません.ある部分に困難があれば、なぜ困難があるのかを盲目的に強要するのではなく、理解して解決する能力を持つべきだ.
いったん会社に入ったら、開発は絶対に一人でやるものではありません.チームパートナーがいて、コミュニケーションは開発者が避けられない重要な宿命です.個人の開発力を増やすことも重要だが、残りの99の航海隊プロジェクトの中で、このコミュニケーション能力を育成する時間が増えることを望んでいる.
URL
ワイヤフレーム-https://ovenapp.io/view/gMfUj8EvR4DBv1FG6g5BwpVkd6ur0LrA#sNWSj
コンセプト企画-https://www.notion.so/26-ac379cabede94755ae8303bba6f9361c
github - https://github.com/Sparta-MungMung/mungmung_client
インプリメンテーションドメイン-http://munghospital.shop/
プロジェクト概要YouTube url-https://www.youtube.com/watch?v=Sd98UjrPmB4
Reference
この問題について([WIL 6週間]航海99組プロジェクト愛犬動物病院予約プラットフォームwith reaction), 我々は、より多くの情報をここで見つけました https://velog.io/@hoon_dev/WIL-6주차-항해-99-팀프로젝트-애견동물병원-예약-플랫폼-with-리액트テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol