All files / src/hooks useArticles.ts

100% Statements 50/50
100% Branches 4/4
100% Functions 7/7
100% Lines 46/46

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 795x   5x 5x 5x                             5x 2x 2x         1x 1x 1x   1x 3x   1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x   1x 6x 6x 3x 3x 3x 3x 3x 6x 3x 3x 3x   1x     5x 4x   4x 4x 2x 2x 2x 1x   1x         4x    
import React from 'react';
 
import { endpoints } from '@/constants';
import { getApiClient, GoogleSheetsApiResponse } from '@/lib';
import { handleError } from '@/utils/errors';
 
export type ArticleData = {
  'title_ja-JP'?: string;
  'title_en-US'?: string;
  'body_ja-JP'?: string;
  'body_en-US'?: string;
  url?: string;
  tags?: string[];
  likesCount?: number;
  stocksCount?: number;
  commentsCount?: number;
  image?: string;
};
 
const fetchData = async () => {
  const client = getApiClient();
  const [pickupResponse, metadataResponse] = await Promise.all([
    client.get<GoogleSheetsApiResponse>(endpoints.getArticlesPickup),
    client.get<GoogleSheetsApiResponse>(endpoints.getArticlesMetadata),
  ]);
 
  const pickupHeader = pickupResponse.data.values[0];
  const pickup_id = pickupHeader.indexOf('id');
  const pickup_data = pickupHeader.indexOf('data');
 
  const buffer: { [key: string]: ArticleData } = {};
  pickupResponse.data.values.slice(1).forEach((row) => (buffer[row[pickup_id]] = { image: row[pickup_data] }));
 
  const metadataHeader = metadataResponse.data.values[0];
  const metadata_id = metadataHeader.indexOf('id');
  const metadata_titleJaJp = metadataHeader.indexOf('title_ja-JP');
  const metadata_titleEnUs = metadataHeader.indexOf('title_en-US');
  const metadata_bodyJaJp = metadataHeader.indexOf('body_ja-JP');
  const metadata_bodyEnUs = metadataHeader.indexOf('body_en-US');
  const metadata_tags = metadataHeader.indexOf('tags');
  const metadata_url = metadataHeader.indexOf('url');
  const metadata_likesCount = metadataHeader.indexOf('likes_count');
  const metadata_stocksCount = metadataHeader.indexOf('stocks_count');
  const metadata_commentsCount = metadataHeader.indexOf('comments_count');
 
  metadataResponse.data.values.forEach((row) => {
    const id = row[metadata_id];
    if (!Object.keys(buffer).includes(id)) return;
    buffer[id]['title_ja-JP'] = row[metadata_titleJaJp];
    buffer[id]['title_en-US'] = row[metadata_titleEnUs];
    buffer[id]['body_ja-JP'] = row[metadata_bodyJaJp];
    buffer[id]['body_en-US'] = row[metadata_bodyEnUs];
    buffer[id].url = row[metadata_url];
    buffer[id].tags = row[metadata_tags].split(',').map((t) => t.trim());
    buffer[id].likesCount = Number(row[metadata_likesCount]);
    buffer[id].stocksCount = Number(row[metadata_stocksCount]);
    buffer[id].commentsCount = Number(row[metadata_commentsCount]);
  });
  return buffer;
};
 
export const useArticles = (ready: boolean) => {
  const [cache, setCache] = React.useState<{ [key: string]: ArticleData }>();
 
  React.useEffect(() => {
    if (ready && !cache)
      (async () => {
        try {
          const data = await fetchData();
          setCache(data);
        } catch (e) {
          handleError(e);
        }
      })();
  }, [ready, cache]);
 
  return cache;
};