aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/FFXIVItemPrice.tsx
blob: d65b3ca67a07f877ab099c8d18f4284946ab0137 (plain) (blame)
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import React, { useState, useEffect } from 'react';

interface FFXIVItemPriceProps {
  itemId: number;
  itemName: string;
  itemImageUrl: string;
}

const FFXIVItemPrice: React.FC<FFXIVItemPriceProps> = ({ itemId = 5530, itemName="Coke", itemImageUrl="https://xivapi.com/i/021000/021462_hr1.png"}) => {
  const [selectedWorld, setSelectedWorld] = useState<string | null>(null);
  const [dailySaleVelocity, setDailySaleVelocity] = useState<number | null>(null);
  const [averageSalePrice, setAverageSalePrice] = useState<number | null>(null);
  const [inputQuantity, setInputQuantity] = useState<number>(0);
  const [potentialGil, setPotentialGil] = useState<number>(0);
  const [dataSource, setDataSource] = useState<string>('world');

  const fetchData = (attempt: number = 1) => {
    fetch(`https://universalis.app/api/v2/aggregated/${selectedWorld}/${itemId}`)
      .then(response => response.json())
      .then(data => {
        let result = data.results[0];
        try {
          setDailySaleVelocity(Math.round(result.nq.dailySaleVelocity.world.quantity));
          setAverageSalePrice(Math.round(result.nq.averageSalePrice.world.price));
          setDataSource('world');
        } catch (error) {
          try {
            setDailySaleVelocity(Math.round(result.nq.dailySaleVelocity.dc.quantity));
            setAverageSalePrice(Math.round(result.nq.averageSalePrice.dc.price));
            setDataSource('dc');
          } catch (error) {
            try {
              setDailySaleVelocity(Math.round(result.nq.dailySaleVelocity.region.quantity));
              setAverageSalePrice(Math.round(result.nq.averageSalePrice.region.price));
              setDataSource('region');
            } catch (error) {
              console.error('Error fetching data:', error);
              if (attempt < 3) {
                setTimeout(() => fetchData(attempt + 1), 5000);
              }
            }
          }
        }
      })
      .catch(error => {
        console.error(`Error fetching data (attempt ${attempt}):`, error);
        if (attempt < 3) {
          setTimeout(() => fetchData(attempt + 1), 5000);
        }
      });
  };

  useEffect(() => {
    const savedWorld = localStorage.getItem('selectedWorld');
    if (savedWorld) {
      setSelectedWorld(savedWorld);
    } else {
      setSelectedWorld('Midgardsormr');
    }

    fetchData();
  }, [itemId, selectedWorld]);

  const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const quantity = parseInt(e.target.value, 10);
    setInputQuantity(quantity);
    setPotentialGil(quantity * (averageSalePrice || 0));
  };

  const formatNumber = (number: number | null) => {
    return number !== null ? new Intl.NumberFormat().format(number) : 'N/A';
  };

  return (
    <div className="ffxiv-container">
      <div className="ffxiv-header">
        <a href={"https://universalis.app/market/" + itemId} className="no-underline">
          <h1 className="ffxiv-h1">{itemName}</h1>
        </a>
        <img src={itemImageUrl} alt={itemName} className="ffxiv-item-icon" />
      </div>
      <table className="ffxiv-table">
        <tbody>
          <tr>
            <td className="ffxiv-label">Average Price/Item:</td>
            <td className="ffxiv-value">{formatNumber(averageSalePrice)} gil</td>
          </tr>
          <tr>
            <td className="ffxiv-label">Daily Sale Velocity:</td>
            <td className="ffxiv-value">{formatNumber(dailySaleVelocity)} items</td>
          </tr>
          <tr>
            <td className="ffxiv-label">Enter Quantity:</td>
            <td>
              <input
                type="number"
                value={inputQuantity}
                onChange={handleInputChange}
                placeholder="Enter quantity"
                className="ffxiv-input"
              />
            </td>
          </tr>
          <tr>
            <td className="ffxiv-label">Potential Gil Earnings:</td>
            <td className="ffxiv-value">{formatNumber(potentialGil)} gil</td>
          </tr>
        </tbody>
      </table>
      <footer>
      {dataSource === 'dc' ? 'Datacenter Fallback ' : dataSource === 'region' ? 'Regional Fallback ' : ''}
      {selectedWorld} Marketboard Data provided by Universalis API. <a className="eorzeadb_link" href="#" onClick={(e) => { e.preventDefault(); fetchData(); }}>Click here to reload data</a>
        <br />
      </footer>
    </div>
  );
};

export default FFXIVItemPrice;
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage