diff options
| -rw-r--r-- | src/components/AnotherComponent.tsx | 28 | ||||
| -rw-r--r-- | src/components/FFXIVItemPrice.tsx | 83 | ||||
| -rw-r--r-- | src/components/FFXIVWorldSelector.tsx | 17 | ||||
| -rw-r--r-- | src/content/blog/ffxiv-gil-making.mdx | 13 | ||||
| -rw-r--r-- | src/styles/ffxiv-selector.css | 72 |
5 files changed, 172 insertions, 41 deletions
diff --git a/src/components/AnotherComponent.tsx b/src/components/AnotherComponent.tsx deleted file mode 100644 index f74e924..0000000 --- a/src/components/AnotherComponent.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import React, { useState, useEffect } from 'react'; - -const AnotherComponent: React.FC = () => { - const [selectedWorld, setSelectedWorld] = useState<string | null>(null); - - useEffect(() => { - // Load selected world from localStorage - const savedWorld = localStorage.getItem('selectedWorld'); - if (savedWorld) { - setSelectedWorld(savedWorld); - } - }, []); - - return ( - <div> - <p>Selected World: {selectedWorld}</p> - <button onClick={() => { - const newWorld = 'New World'; - setSelectedWorld(newWorld); - localStorage.setItem('selectedWorld', newWorld); // Save to localStorage - }}> - Change World - </button> - </div> - ); -}; - -export default AnotherComponent;
\ No newline at end of file diff --git a/src/components/FFXIVItemPrice.tsx b/src/components/FFXIVItemPrice.tsx new file mode 100644 index 0000000..8f265fc --- /dev/null +++ b/src/components/FFXIVItemPrice.tsx @@ -0,0 +1,83 @@ +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); + + useEffect(() => { + const savedWorld = localStorage.getItem('selectedWorld'); + if (savedWorld) { + setSelectedWorld(savedWorld); + } else { + setSelectedWorld('Midgardsormr'); + } + + fetch(`https://universalis.app/api/v2/aggregated/${selectedWorld}/${itemId}`) + .then(response => response.json()) + .then(data => { + const result = data.results[0]; + setDailySaleVelocity(Math.round(result.nq.dailySaleVelocity.world.quantity)); + setAverageSalePrice(Math.round(result.nq.averageSalePrice.world.price)); + }) + .catch(error => console.error('Error fetching data:', error)); + }, [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"> + <h1 className="ffxiv-h1">{itemName}</h1> + <img src={itemImageUrl} alt={itemName} className="ffxiv-item-icon" /> + </div> + <table className="ffxiv-table"> + <tbody> + <tr> + <td className="ffxiv-label">Daily Sale Velocity:</td> + <td className="ffxiv-value">{formatNumber(dailySaleVelocity)} items</td> + </tr> + <tr> + <td className="ffxiv-label">Average Price/Item:</td> + <td className="ffxiv-value">{formatNumber(averageSalePrice)} gil</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>{selectedWorld} Marketboard Data provided by Universalis API</footer> + </div> + ); +}; + +export default FFXIVItemPrice;
\ No newline at end of file diff --git a/src/components/FFXIVWorldSelector.tsx b/src/components/FFXIVWorldSelector.tsx index f2dc4cc..63eff07 100644 --- a/src/components/FFXIVWorldSelector.tsx +++ b/src/components/FFXIVWorldSelector.tsx @@ -1,11 +1,15 @@ import React, { useState, useEffect } from 'react'; - +import '../styles/ffxiv-selector.css'; interface World { id: number; name: string; } -const FFXIVWorldSelector: React.FC = () => { +interface FFXIVWorldSelectorProps { + message: string; +} + +const FFXIVWorldSelector: React.FC<FFXIVWorldSelectorProps> = ({ message = "Select a World" }) => { const [worlds, setWorlds] = useState<World[]>([]); const [selectedWorld, setSelectedWorld] = useState<string | null>(null); @@ -40,9 +44,9 @@ const FFXIVWorldSelector: React.FC = () => { }; return ( - <div> - <label htmlFor="world-select">Select a world: </label> - <select id="world-select" onChange={handleWorldChange} value={selectedWorld || ''}> + <div className="ffxiv-container"> + <label htmlFor="world-select" className="ffxiv-label">{message}</label> + <select id="world-select" onChange={handleWorldChange} value={selectedWorld || ''} className="ffxiv-select"> <option value="">--Please choose an option--</option> {worlds.map((world) => ( <option key={world.id} value={world.name}> @@ -50,8 +54,7 @@ const FFXIVWorldSelector: React.FC = () => { </option> ))} </select> - {selectedWorld && <p>Selected World: {selectedWorld}</p>} - <button onClick={handleApplyClick}>Apply</button> + <button onClick={handleApplyClick} className="ffxiv-button">Apply</button> </div> ); }; diff --git a/src/content/blog/ffxiv-gil-making.mdx b/src/content/blog/ffxiv-gil-making.mdx index 002ab8c..eb35a28 100644 --- a/src/content/blog/ffxiv-gil-making.mdx +++ b/src/content/blog/ffxiv-gil-making.mdx @@ -5,15 +5,16 @@ pubDate: "2024-08-23" --- import '../../styles/ffxiv-gil-making.css' import FFXIVWorldSelector from '../../components/FFXIVWorldSelector'; -import AnotherComponent from '../../components/AnotherComponent'; - -*Enter the world you play on below to get crowdsourced marketboard prices* -<FFXIVWorldSelector client:load /> +import FFXIVItemPrice from '../../components/FFXIVItemPrice'; +<FFXIVWorldSelector client:load message="Set your home world to get crowdsourced marketboard information!" /> I've seen a lot of these "making gil without crafting" or "making gil with combat job" guides during my time with the game. A lot of these videos and guides are fine, but in my opinion they neglect a lot of the late game and niche options that are available to players. -This post will attempt to be a somewhat comprehensive guide to making gil without having to level any crafting jobs (cause I get it, crafting is not for everyone). -<AnotherComponent client:load/>
\ No newline at end of file +This post will attempt to be a somewhat comprehensive guide/info sheet to making gil without having to level any crafting jobs (cause I get it, crafting is not for everyone). + +Keep in mind though that crafters are probably one of the most consistent methods of getting gil. There will be a lot more "instability" with these methods. + +# Grand Company Seals
\ No newline at end of file diff --git a/src/styles/ffxiv-selector.css b/src/styles/ffxiv-selector.css new file mode 100644 index 0000000..efad540 --- /dev/null +++ b/src/styles/ffxiv-selector.css @@ -0,0 +1,72 @@ +.ffxiv-container { + background-color: #1a1a1a; + color: #e2c08d; + padding: 10px; + border: 2px solid #e2c08d; + border-radius: 10px; + font-family: 'Arial', serif; + max-width: 500px; + margin: auto; +} + +.ffxiv-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 10px; +} + +.ffxiv-item-icon { + width: 50px; + height: 50px; +} + +.ffxiv-h1 { + font-size: 1.5em; + color: #e2c08d; + margin: 0; +} + +.ffxiv-table { + width: 100%; + border-collapse: collapse; +} + +.ffxiv-button { + background-color: #333; + color: #e2c08d; + border: 1px solid #e2c08d; + padding: 5px; + padding-left: 10px; + padding-right: 10px; + margin-left: 10px; + border-radius: 5px; + cursor: pointer; +} + +.ffxiv-table td { + padding: 5px; + border: 1px solid #e2c08d; +} + +.ffxiv-label { + font-size: 1em; +} + +.ffxiv-value { + font-size: 1em; +} + +.ffxiv-input { + background-color: #333; + color: #e2c08d; + border: 1px solid #e2c08d; + padding: 5px; + border-radius: 5px; + width: 100%; + box-sizing: border-box; +} + +.ffxiv-input::placeholder { + color: #e2c08d; +}
\ No newline at end of file |
