Skip to content

Commit

Permalink
Merge pull request #146 from FltSv/140-eslint-warn-fix
Browse files Browse the repository at this point in the history
#140 ESLintで発生していた警告の修正
  • Loading branch information
FltSv authored Oct 20, 2024
2 parents 02377db + dedb8f2 commit 218ffde
Show file tree
Hide file tree
Showing 13 changed files with 677 additions and 450 deletions.
7 changes: 4 additions & 3 deletions Hosting/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export default tseslint.config(
'globalThis',
],
// 関数の記述方法を関数式(アロー関数を含む)に統一
'func-style': ['warn', 'expression', { allowArrowFunctions: true }],
'func-style': ['error', 'expression', { allowArrowFunctions: true }],
'arrow-body-style': ['error', 'as-needed'], // アロー関数の本体の記述方法を制限
},
},
Expand Down Expand Up @@ -140,7 +140,7 @@ export default tseslint.config(
},
],
'functional/immutable-data': [
'warn', // オブジェクトの変更を警告
'error', // オブジェクトの変更を警告
{
ignoreImmediateMutation: true, // 変数に代入する前の即時変更を許可
ignoreClasses: true, // クラスの変更を許可
Expand All @@ -149,6 +149,7 @@ export default tseslint.config(
'window.location.href',
],
ignoreAccessorPattern: [
'window.**', // windowオブジェクトの変更を許可
'**.current.**', // React.useRefのcurrentプロパティへの変更を許可
'**.displayName', // React componentのdisplayNameプロパティへの変更を許可
'**.scrollTop', // スクロール位置の変更を許可
Expand Down Expand Up @@ -177,7 +178,7 @@ export default tseslint.config(
...reactPlugin.configs['jsx-runtime'].rules,
'react/prop-types': 'off',
'react/hook-use-state': 'error', // useStateの返り値の命名を統一
'react/jsx-no-bind': 'warn', // JSX内での関数記述を禁止し、renderごとの関数生成を防止
'react/jsx-no-bind': 'error', // JSX内での関数記述を禁止し、renderごとの関数生成を防止
'react/jsx-boolean-value': 'error', // boolean型のPropsの渡し方を統一
'react/jsx-curly-brace-presence': 'error', // 不要な中括弧を禁止
'react/jsx-no-useless-fragment': 'error', // 不要なReact Fragmentの使用を禁止
Expand Down
41 changes: 20 additions & 21 deletions Hosting/src/Auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,16 @@ type providerTypes = 'google' | 'facebook' | 'email';
* @param email メールアドレス
* @param pass パスワード
*/
export async function loginWithEmail(email: string, pass: string) {
export const loginWithEmail = async (email: string, pass: string) => {
const auth = getAuth();
return await signInWithEmailAndPassword(auth, email, pass);
}
};

/**
* メール・パスワードによる新規登録
* @returns
*/
export async function signupWithEmail(email: string, pass: string) {
export const signupWithEmail = async (email: string, pass: string) => {
const auth = getAuth();
const userCredential = await createUserWithEmailAndPassword(
auth,
Expand All @@ -35,43 +35,42 @@ export async function signupWithEmail(email: string, pass: string) {
// メールアドレス確認メールを送信する
await sendEmailVerification(userCredential.user);
return userCredential;
}
};

/** Googleログイン・新規登録 */
export async function loginWith(providerType: providerTypes) {
let provider;
switch (providerType) {
case 'google':
provider = new GoogleAuthProvider();
break;
export const loginWith = async (providerType: providerTypes) => {
const provider = (() => {
switch (providerType) {
case 'google':
return new GoogleAuthProvider();

case 'facebook':
provider = new FacebookAuthProvider();
break;
case 'facebook':
return new FacebookAuthProvider();

default:
throw new Error('Invalid provider type');
}
default:
throw new Error('Invalid provider type');
}
})();

// ポップアップでログイン
return await signInWithPopup(getAuth(), provider).catch((error: unknown) => {
console.error(error);
});
}
};

/**
* ログアウト
*/
export async function signOut() {
export const signOut = async () => {
await getAuth().signOut();
}
};

/**
* メールアドレス確認メールを再送信する
*/
export async function sendVerifyEmail() {
export const sendVerifyEmail = async () => {
const user = getAuth().currentUser;
if (user) {
await sendEmailVerification(user);
}
}
};
122 changes: 68 additions & 54 deletions Hosting/src/Data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,20 +37,12 @@ const imageCompOptions: Options = {
maxWidthOrHeight: 1000,
};

function getCreatorStorageUrl(userId: string) {
return `https://firebasestorage.googleapis.com/v0/b/gallery-found.appspot.com/o/creators%2F${userId}%2F`;
}
const getCreatorStorageUrl = (userId: string) =>
`https://firebasestorage.googleapis.com/v0/b/gallery-found.appspot.com/o/creators%2F${userId}%2F`;

export async function getCreatorData(user: User) {
export const getCreatorData = async (user: User) => {
const userId = user.uid;
const creatorUrl = getCreatorStorageUrl(userId);
const creator: Creator = {
name: '',
profile: '',
links: [],
products: [],
exhibits: [],
};

// Firestoreからユーザーデータを取得
const docRef = doc(db, collectionNames.creators, userId).withConverter(
Expand All @@ -61,20 +53,28 @@ export async function getCreatorData(user: User) {
// 作家情報が存在しているか
if (!docSnap.exists()) {
// 存在しない場合、情報は空のままで登録を促す
return creator;
const empty: Creator = {
name: '',
profile: '',
links: [],
products: [],
exhibits: [],
};

return empty;
}

// ドキュメントが存在する場合、詳細を取得
const data = docSnap.data();
console.debug('docSnap.data:', data);

creator.name = data.name ?? '';
creator.profile = data.profile ?? '';
creator.links = data.links ?? [];
const name = data.name ?? '';
const profile = data.profile ?? '';
const links = data.links ?? [];

// 発表作品
const fbProducts = data.products ?? [];
creator.products = fbProducts.map(x => ({
const products = fbProducts.map(x => ({
id: x.id,
title: x.title ?? '',
detail: x.detail ?? '',
Expand All @@ -86,7 +86,7 @@ export async function getCreatorData(user: User) {
// 展示登録
const fbExhibits = data.exhibits ?? [];
const today = new Date();
creator.exhibits = fbExhibits.map(x => ({
const exhibits = fbExhibits.map(x => ({
id: x.id,
title: x.title,
location: x.location,
Expand All @@ -98,19 +98,27 @@ export async function getCreatorData(user: User) {
tmpImageData: '',
}));

const creator: Creator = {
name: name,
profile: profile,
links: links,
products: products,
exhibits: exhibits,
};

console.debug('creator:', creator);
return creator;
}
};

/**
* 値の確定、DBへデータを送信する
*/
export async function setCreatorData(user: User, data: Creator) {
export const setCreatorData = async (user: User, data: Creator) => {
const userId = user.uid;

// 画像のアップロード
await uploadImageData(user, data.products);
await uploadImageData(user, data.exhibits);
const products = await uploadImageData(user, data.products);
const exhibits = await uploadImageData(user, data.exhibits);

// DB更新
const docRef = doc(db, collectionNames.creators, userId).withConverter(
Expand All @@ -120,13 +128,13 @@ export async function setCreatorData(user: User, data: Creator) {
name: data.name,
profile: data.profile,
links: data.links,
products: data.products.map(x => ({
products: products.map(x => ({
id: x.id,
title: x.title,
detail: x.detail,
image: x.srcImage,
})),
exhibits: data.exhibits.map(x => ({
exhibits: exhibits.map(x => ({
id: x.id,
title: x.title,
location: x.location,
Expand All @@ -139,7 +147,7 @@ export async function setCreatorData(user: User, data: Creator) {

// 使用されていない画像の削除
// 使用中の画像
const usingImages = [...data.products, ...data.exhibits].map(
const usingImages = [...products, ...exhibits].map(
(x: ImageStatus) => x.srcImage.split('?')[0],
);

Expand All @@ -165,16 +173,19 @@ export async function setCreatorData(user: User, data: Creator) {

// 処理完了
console.debug('complete setCreatorData');
}
};

/**
* tmpImageDataの画像をアップロード、URLを格納
*/
async function uploadImageData(user: User, images: ImageStatus[]) {
const uploadImage = async (image: ImageStatus) => {
const uploadImageData = async <T extends ImageStatus>(
user: User,
images: T[],
): Promise<T[]> => {
const uploadImage = async (image: T) => {
// イメージの更新が無ければスキップ
if (image.tmpImageData === '') {
return;
return image;
}

// blobURL→blobオブジェクトへ変換
Expand All @@ -193,15 +204,17 @@ async function uploadImageData(user: User, images: ImageStatus[]) {

const url = await getDownloadURL(result.ref);
const name = result.metadata.name;
image.srcImage = url.match(`${name}.*`)?.[0] ?? '';
const srcImage = url.match(`${name}.*`)?.[0] ?? '';
const newImage: T = { ...image, srcImage: srcImage };
return newImage;
};

const tasks = images.map(exhibit => uploadImage(exhibit));
await Promise.all(tasks);
}
const tasks = images.map(uploadImage);
return await Promise.all(tasks);
};

/** すべての展示情報の取得 */
export async function getAllExhibits() {
export const getAllExhibits = async () => {
const creatorsSnap = await getDocs(
collection(db, collectionNames.creators).withConverter(fbCreatorConverter),
);
Expand Down Expand Up @@ -231,35 +244,36 @@ export async function getAllExhibits() {

const resolvedExhibits = await Promise.all(exhibitsPromises);
return resolvedExhibits.flat();
}
};

export interface GalleryExhibits {
gallery: Gallery;
exhibits: Exhibit[];
}

/** ギャラリー情報と関連する展示の配列を取得 */
export async function getGalleryExhibits() {
export const getGalleryExhibits = async () => {
const galleries = await getGalleries();
const exhibits = await getAllExhibits();

const array: GalleryExhibits[] = [];
const groupedExhibits = Map.groupBy(exhibits, x => x.location);

Map.groupBy(exhibits, x => x.location).forEach((value, key) => {
const gallery = galleries.find(x => x.name === key);
if (gallery === undefined) return;

array.push({
gallery: gallery,
exhibits: value,
});
});
const array = Array.from(groupedExhibits.entries())
.map(([key, value]) => {
const gallery = galleries.find(x => x.name === key);
if (gallery === undefined) return null;
return {
gallery: gallery,
exhibits: value,
};
})
.filter((x): x is GalleryExhibits => x !== null);

return array;
}
};

/** ギャラリー情報の一覧を取得 */
export async function getGalleries() {
export const getGalleries = async () => {
const colRef = collection(db, collectionNames.galleries);
const querySnap = await getDocs(colRef.withConverter(fbGalleryConverter));

Expand All @@ -268,20 +282,20 @@ export async function getGalleries() {
const { latitude, longitude } = data.latLng.toJSON();
return { ...data, id: doc.id, latLng: { lat: latitude, lng: longitude } };
});
}
};

/** ギャラリー情報を追加 */
export async function addGallery(data: Gallery) {
export const addGallery = async (data: Gallery) => {
const { lat, lng } = await getLatLngFromAddress(data.location);
const { id, ...firebaseData } = { ...data, latLng: new GeoPoint(lat, lng) };
void id;

const docRef = doc(db, collectionNames.galleries, getUlid());
await setDoc(docRef.withConverter(fbGalleryConverter), firebaseData);
}
};

/** 住所から緯度経度を取得する */
async function getLatLngFromAddress(address: string) {
const getLatLngFromAddress = async (address: string) => {
const geocoder = new google.maps.Geocoder();
const geocodingTask = new Promise<google.maps.GeocoderResult[]>(
(resolve, reject) =>
Expand All @@ -306,14 +320,14 @@ async function getLatLngFromAddress(address: string) {
);

return results[0].geometry.location.toJSON();
}
};

/** 日付の期間の表示値を返す */
export function getDatePeriodString(start: Date, end: Date) {
export const getDatePeriodString = (start: Date, end: Date) => {
const startString = start.toLocaleDateString();
const endString = end.toLocaleDateString();
return `${startString}${endString}`;
}
};

/** 作家 */
export interface Creator {
Expand Down
8 changes: 3 additions & 5 deletions Hosting/src/ULID.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { ulid, decodeTime } from 'ulidx';

export function getUlid() {
return ulid();
}
export const getUlid = () => ulid();

export function toDate(ulid: string) {
export const toDate = (ulid: string) => {
const unixTime = decodeTime(ulid);
return new Date(unixTime);
}
};
Loading

0 comments on commit 218ffde

Please sign in to comment.