From be3a333efca9cc5a843df76f376201d936307260 Mon Sep 17 00:00:00 2001 From: Ajlanclos Date: Thu, 12 Sep 2024 22:34:27 -0500 Subject: [PATCH 01/12] started work on message builder --- public/avatar.png | Bin 0 -> 6038 bytes .../MessageBuilder/MessageBuilder.tsx | 101 ++++++++++++++++++ src/index.scss | 20 ++++ src/pages/MissionPage.tsx | 47 +++++++- 4 files changed, 164 insertions(+), 4 deletions(-) create mode 100644 public/avatar.png create mode 100644 src/components/MessageBuilder/MessageBuilder.tsx diff --git a/public/avatar.png b/public/avatar.png new file mode 100644 index 0000000000000000000000000000000000000000..e33d249169e72150969109cb44c0c982b0524c95 GIT binary patch literal 6038 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 1 ? "Split Stack" : "Single" + } - (${Object.keys(stackData.type) + .map((key: any) => `${key}: ${stackData.type[key]}`) + .join(", ")})`; + + const formatMessage = () => { + const msg = ` +${ + discordTag ? discordTag : "{DISCORD_TAG}" +} Hey commanders! I have a stack that is completed and ready for sharing. +I am available between ${startDate ? startDate : "{START_DATE}"} and ${ + endDate ? endDate : "{END_DATE}" + }. + +**Details:** +Stack Size: ${stackData.size} +Stack Value: ${formatNumber(stackData.value)} +Stack Type: ${stackTypeMessage} + +Generated by Trakkr + `; + + setMessage(msg); + }; + + const onDiscordTagChange = (e: any) => { + setDiscordTag(e.target.value); + }; + + const onStartDateChange = (e: any) => { + setStartDate(e.target.value); + }; + + const onEndDateChange = (e: any) => { + setEndDate(e.target.value); + }; + + useEffect(() => { + console.log("stackdata: ", stackData); + formatMessage(); + }, [discordTag]); + + return ( +
+
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ + +
+
+
+ ); +} + +export default MessageBuilder; diff --git a/src/index.scss b/src/index.scss index 845d1f4..10c4fe8 100644 --- a/src/index.scss +++ b/src/index.scss @@ -165,4 +165,24 @@ input { outline: none; border-color: var(--accent); } +} + +textarea { + background: $gray-dark; + border: 1px solid $gray-light; + margin: 0; +} + +.p-dialog { + background: $gray2; + padding: 1rem; + border: 1px solid $gray-light; + .p-dialog-header { + text-transform: uppercase; + font-size: 16px; + font-weight: bold; + } +} +.p-dialog-mask { + background-color: rgba(0,0,0,.75); } \ No newline at end of file diff --git a/src/pages/MissionPage.tsx b/src/pages/MissionPage.tsx index 8459a59..c0d8da5 100644 --- a/src/pages/MissionPage.tsx +++ b/src/pages/MissionPage.tsx @@ -1,4 +1,5 @@ import { useEffect, useState } from "react"; +import { Dialog } from "primereact/dialog"; import ActiveMissions from "../components/ActiveMissions/ActiveMissions"; import CompleteMissions from "../components/CompleteMissions/CompleteMissions"; import TabMenu from "../components/TabMenu/TabMenu"; @@ -11,6 +12,7 @@ import { useCommanderState } from "../context/Commander"; import Empty from "../components/Empty/Empty"; import Config from "../components/Config/Config"; import dayjs from "dayjs"; +import MessageBuilder from "../components/MessageBuilder/MessageBuilder"; function MissionPage() { const { activeCommander, fetchedAt, fetchMissionData, state }: any = @@ -26,7 +28,7 @@ function MissionPage() { const [commodities, setCommodities]: any = useState({}); const [commodityConfig, setCommodityConfig]: any = useState({}); const [totalInvestment, setTotalInvestment]: any = useState(0); - const [totalProfit, setTotalProfit]: any = useState(0); + const [builderVisible, setBuilderVisible]: any = useState(false); const onMenuClick = (updatedMenu: any) => { setMenuItems(updatedMenu); @@ -125,12 +127,27 @@ function MissionPage() { }, null); }; + const handleStackType = () => { + const stationCount: { [key: string]: number } = {}; + + completedMissions.forEach((mission: any) => { + const station = mission.DestinationStation; + if (station in stationCount) { + stationCount[station] += 1; + } else { + stationCount[station] = 1; + } + }); + + return stationCount; + }; + useEffect(() => { fetchMissionData(); }, []); useEffect(() => { - if(!state || state && !state.commodityConfig) return; + if (!state || (state && !state.commodityConfig)) return; setCommodityConfig(state.commodityConfig); }, [state]); @@ -165,8 +182,8 @@ function MissionPage() { const { sortedCommodities, investment } = calculateCommodities(commodityConfig); - setCommodities(sortedCommodities); - setTotalInvestment(investment); + setCommodities(sortedCommodities); + setTotalInvestment(investment); }, [acceptedMissions, completedMissions]); return ( @@ -215,12 +232,34 @@ function MissionPage() { ) : ( )} +
+ +
Last update:{" "} {dayjs(fetchedAt).fromNow()} + { + if (!builderVisible) return; + setBuilderVisible(false); + }} + > + + ); } From ca4d9016da52d2450ebe94603d9568eb431fd273 Mon Sep 17 00:00:00 2001 From: IndorilReborn Date: Fri, 13 Sep 2024 17:27:05 +0300 Subject: [PATCH 02/12] add release action with build attestation --- .github/workflows/release.yml | 47 +++++++++++++++++++++++++++++++++++ package.json | 2 +- 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..83c0983 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,47 @@ +name: Build/release + +permissions: + id-token: write + contents: write + attestations: write + +on: + push: + tags: + - 'v[0-9]+.[0-9]+.[0-9]+*' +jobs: + release: + runs-on: windows-latest + + steps: + - name: Check out Git repository + uses: actions/checkout@v1 + with: + fetch-depth: 1 + + - name: Install Node.js, NPM and Yarn + uses: actions/setup-node@v4.0.3 + with: + node-version: '20.x' + + - name: Install dependencies + run: npm install + + - name: Build app + id: build + run: npm run build + + - name: Attest build + id: attestation + if: steps.build.outcome == 'success' + uses: actions/attest-build-provenance@v1 + with: + subject-path: dist/Trakkr Setup *.exe + + - name: Upload files to release + uses: softprops/action-gh-release@v2 + with: + files: | + dist/Trakkr Setup *.exe + ${{ steps.attestation.outputs.bundle-path }} + diff --git a/package.json b/package.json index 1c356e6..7a9771a 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "build": "vite build && npm run electron-pack", "serve": "vite preview", "electron-dev": "electron .", - "electron-pack": "electron-builder", + "electron-pack": "electron-builder --publish=never", "electron-prep": "xcopy electron\\main.js dist\\electron\\main.js && xcopy electron\\preload.js dist\\electron\\preload.js" }, "dependencies": { From 1901366069f690698ff270e0b82fd7b97ff321ec Mon Sep 17 00:00:00 2001 From: Ajlanclos Date: Fri, 13 Sep 2024 10:28:38 -0500 Subject: [PATCH 03/12] can copy message and convert to epoch time --- .../MessageBuilder/MessageBuilder.tsx | 125 +++++++++++++----- 1 file changed, 94 insertions(+), 31 deletions(-) diff --git a/src/components/MessageBuilder/MessageBuilder.tsx b/src/components/MessageBuilder/MessageBuilder.tsx index 5e427f5..5c63dc1 100644 --- a/src/components/MessageBuilder/MessageBuilder.tsx +++ b/src/components/MessageBuilder/MessageBuilder.tsx @@ -2,53 +2,101 @@ import { useEffect, useState } from "react"; import { formatNumber } from "../../helpers/formatNumber"; function MessageBuilder({ stackData }: any) { + const [trakkrUrl]: any = useState("https://github.com/skybreakdigital/trakkr-app"); const [message, setMessage]: any = useState(""); const [discordTag, setDiscordTag]: any = useState(""); const [startDate, setStartDate]: any = useState(""); const [endDate, setEndDate]: any = useState(""); + const [shareDate, setShareDate]: any = useState(""); + const [startTime, setStartTime]: any = useState(""); + const [endTime, setEndTime]: any = useState(""); - const stackTypeMessage = `${ - Object.keys(stackData.type).length > 1 ? "Split Stack" : "Single" - } - (${Object.keys(stackData.type) - .map((key: any) => `${key}: ${stackData.type[key]}`) - .join(", ")})`; + const stackTypeMessage = `${Object.keys(stackData.type).length > 1 ? "Split Stack" : "Single" + } - (${Object.keys(stackData.type) + .map((key: any) => `${key}: ${stackData.type[key]}`) + .join(", ")})`; const formatMessage = () => { - const msg = ` -${ - discordTag ? discordTag : "{DISCORD_TAG}" -} Hey commanders! I have a stack that is completed and ready for sharing. -I am available between ${startDate ? startDate : "{START_DATE}"} and ${ - endDate ? endDate : "{END_DATE}" - }. + const msg = `${discordTag ? discordTag : "{DISCORD_TAG}"} Hey commanders! I have a stack that is completed and ready for sharing. I am available between ${startDate ? startDate : "{START_DATE}"} and ${endDate ? endDate : "{END_DATE}"}. **Details:** -Stack Size: ${stackData.size} -Stack Value: ${formatNumber(stackData.value)} -Stack Type: ${stackTypeMessage} +Stack Size: \`${stackData.size === 20 ? 'Full Stack' : 'Partial Stack'} (${stackData.size} Missions)\` +Stack Value: \`${formatNumber(stackData.value)}\` +Stack Type: \`${stackTypeMessage}\` -Generated by Trakkr +Generated by [Trakkr](<${trakkrUrl}>) `; setMessage(msg); }; + const onCopyText = () => { + navigator.clipboard.writeText(message) + .then(() => { + alert('Message was copied to clipboard.') + }) + .catch((error) => { + console.error('Failed to copy: ', error); + }); + } + + const formatStartDate = () => { + const [hour, minute] = startTime.split(':'); + + const date = new Date(shareDate); + + date.setHours(hour); + date.setMinutes(minute); + date.setSeconds(0); + + const epochTime = Math.floor(date.getTime() / 1000); + + setStartDate(``); + } + + const formatEndDate = () => { + const [hour, minute] = endTime.split(':'); + + const date = new Date(shareDate); + + date.setHours(hour); + date.setMinutes(minute); + date.setSeconds(0); + + const epochTime = Math.floor(date.getTime() / 1000); + + setEndDate(``); + } + const onDiscordTagChange = (e: any) => { setDiscordTag(e.target.value); }; const onStartDateChange = (e: any) => { - setStartDate(e.target.value); + setShareDate(e.target.value); }; - const onEndDateChange = (e: any) => { - setEndDate(e.target.value); + const onTimeChange = (e: any) => { + const { name, value } = e.target; + + if (name === 'startTime') { + setStartTime(value); + } else { + setEndTime(value); + } }; useEffect(() => { console.log("stackdata: ", stackData); formatMessage(); - }, [discordTag]); + }, [discordTag, startDate, endDate]); + + useEffect(() => { + if (!startTime && !endTime) return; + + formatStartDate(); + formatEndDate(); + }, [shareDate, startTime, endTime]); return (
@@ -67,21 +115,36 @@ Generated by Trakkr
-
- - +
+
+ + +
+
+ + +
+
+
+
From e37c692c85b81f19ceffb9b7caa32dee1c9816ff Mon Sep 17 00:00:00 2001 From: Ajlanclos Date: Fri, 13 Sep 2024 10:58:06 -0500 Subject: [PATCH 04/12] small fixes for message builder --- .../MessageBuilder/MessageBuilder.tsx | 100 ++++++++++-------- src/index.scss | 12 +++ src/pages/MissionPage.tsx | 17 ++- 3 files changed, 78 insertions(+), 51 deletions(-) diff --git a/src/components/MessageBuilder/MessageBuilder.tsx b/src/components/MessageBuilder/MessageBuilder.tsx index 5c63dc1..3bb2bd1 100644 --- a/src/components/MessageBuilder/MessageBuilder.tsx +++ b/src/components/MessageBuilder/MessageBuilder.tsx @@ -99,64 +99,70 @@ Generated by [Trakkr](<${trakkrUrl}>) }, [shareDate, startTime, endTime]); return ( -
-
-
- - -
-
- - -
-
-
- +
+ {stackData.size < 20 && ( +
You are sharing only {stackData.size} missions. We suggest sharing a full stack (20), as more Commanders are likely to share with you.
+ )} +
+
+
+
-
- +
+
+
+
+ + +
+
+ + +
+
+
+ +
-
- -
-
-
-
- - +
+
+ + +
+
); } diff --git a/src/index.scss b/src/index.scss index 10c4fe8..bb27f2f 100644 --- a/src/index.scss +++ b/src/index.scss @@ -64,6 +64,15 @@ ul li > div { .bg-primary { background-color: $gray2; } +.alert { + background: rgba($red, .20); + border: 1px solid $red; + padding: .5rem; + margin-top: 1rem; + .fa-solid { + color: $red; + } +} button { border: 0; @@ -80,6 +89,9 @@ button { background: rgba($gray-light, .75); } } + &:disabled { + opacity: .35; + } } .mission-list { diff --git a/src/pages/MissionPage.tsx b/src/pages/MissionPage.tsx index c0d8da5..636f229 100644 --- a/src/pages/MissionPage.tsx +++ b/src/pages/MissionPage.tsx @@ -115,6 +115,13 @@ function MissionPage() { return acceptedValue + completedValue; }; + const calculateCompletedMissionValue = () => { + return completedMissions.reduce( + (total: number, mission: any) => total + (mission.Reward || 0), + 0 + ); + } + const calculateShareDate = () => { const allMissions = [...acceptedMissions, ...completedMissions]; @@ -233,9 +240,11 @@ function MissionPage() { )}
- +
@@ -255,7 +264,7 @@ function MissionPage() { From dfa0d87f65a658fa6498fd7a0aa624151604c662 Mon Sep 17 00:00:00 2001 From: Ajlanclos Date: Fri, 13 Sep 2024 14:01:29 -0500 Subject: [PATCH 05/12] working on small updates --- electron/events/journal.js | 8 ++++++- src/Layout.tsx | 49 ++++++++++++++++++++++++-------------- src/context/Commander.tsx | 7 ++++-- src/index.scss | 10 ++++++++ src/pages/MissionPage.tsx | 14 +++++++---- 5 files changed, 62 insertions(+), 26 deletions(-) diff --git a/electron/events/journal.js b/electron/events/journal.js index d63c59f..19bf3d8 100644 --- a/electron/events/journal.js +++ b/electron/events/journal.js @@ -72,6 +72,13 @@ function sortJournal() { } switch(event) { + case 'LoadGame': + journalData[fid].info = { + ...journalData[fid].info, + ship: parsedEntry.Ship_Localised, + credits: parsedEntry.Credits + } + break; case 'Commander': journalData[fid].info = { ...journalData[fid].info, @@ -81,7 +88,6 @@ function sortJournal() { case 'Loadout': journalData[fid].info = { ...journalData[fid].info, - ship: parsedEntry.Ship, cargo: parsedEntry.CargoCapacity } break; diff --git a/src/Layout.tsx b/src/Layout.tsx index ae47685..f54a1b7 100644 --- a/src/Layout.tsx +++ b/src/Layout.tsx @@ -13,14 +13,31 @@ function Layout() { const [commanderData, setCommanderData]: any = useState({}); const [commander, setCommander]: any = useState({}); + const sortCommanders = (commanderData: any) => { + const sortedEntries = Object.entries(commanderData) + .sort(([keyA], [keyB]) => { + const numA = parseInt(keyA.slice(1), 10); + const numB = parseInt(keyB.slice(1), 10); + + // Sort numerically + return numA - numB; + }); + + return sortedEntries.reduce((obj: any, [key, value]) => { + obj[key] = value; + return obj; + }, {}); + } + useEffect(() => { - if(!missionData) return; - - setCommanderData(missionData); + if (!missionData) return; + + const sortedCommanderData = sortCommanders(missionData); + setCommanderData(sortedCommanderData); }, [missionData]); useEffect(() => { - if(!activeCommander) return; + if (!activeCommander) return; setCommander(activeCommander); }, [activeCommander]); @@ -29,22 +46,18 @@ function Layout() { navigate('/main/missions'); }, []); - if(loading) { - return
loading...
- } - return ( -
- -
- {missionData && ( - - )} - -

Welcome back, {commander?.info?.name}

- -
+
+ +
+ {missionData && ( + + )} + +

Welcome back, {commander?.info?.name}

+
+
) } diff --git a/src/context/Commander.tsx b/src/context/Commander.tsx index b257403..c23c12a 100644 --- a/src/context/Commander.tsx +++ b/src/context/Commander.tsx @@ -10,7 +10,7 @@ export const CommanderProvider = ({ children }: any) => { const [activeCommander, setActiveCommander]: any = useState(null); const [fetchedAt, setFetchedAt]: any = useState(null); const [state, setState]: any = useState({}); - const [loading, setLoading] = useState(true); + const [loading, setLoading] = useState(false); const setCommander = (fid: string) => { window.electron.setState({ activeCommander: missionData[fid] }); @@ -40,7 +40,9 @@ export const CommanderProvider = ({ children }: any) => { } catch (error) { console.error("Error fetching mission data:", error); } finally { - setLoading(false); // Data fetch is complete + setTimeout(() => { + setLoading(false); + }, 3000); } }; @@ -78,6 +80,7 @@ export const CommanderProvider = ({ children }: any) => { // Updates in real-time when the game write to the journal file window.electron.on("journal-file-updated", () => { + setLoading(true); fetchMissionData(); }); diff --git a/src/index.scss b/src/index.scss index bb27f2f..b373167 100644 --- a/src/index.scss +++ b/src/index.scss @@ -197,4 +197,14 @@ textarea { } .p-dialog-mask { background-color: rgba(0,0,0,.75); +} + +.spin { + display: inline-block; + animation: spin 1s linear infinite; +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } } \ No newline at end of file diff --git a/src/pages/MissionPage.tsx b/src/pages/MissionPage.tsx index 636f229..d5bb631 100644 --- a/src/pages/MissionPage.tsx +++ b/src/pages/MissionPage.tsx @@ -15,7 +15,7 @@ import dayjs from "dayjs"; import MessageBuilder from "../components/MessageBuilder/MessageBuilder"; function MissionPage() { - const { activeCommander, fetchedAt, fetchMissionData, state }: any = + const { activeCommander, fetchedAt, fetchMissionData, state, loading }: any = useCommanderState(); const [menuItems, setMenuItems]: any = useState([ @@ -248,10 +248,14 @@ function MissionPage() {
- - Last update:{" "} - {dayjs(fetchedAt).fromNow()} - +
+ {loading && ( +
+ +
+ )} +
Last update: {dayjs(fetchedAt).fromNow()}
+
Date: Fri, 13 Sep 2024 15:03:29 -0500 Subject: [PATCH 06/12] updates to duration left on expiry --- electron/events/journal.js | 6 +++ .../ActiveMissions/ActiveMission.scss | 6 ++- .../ActiveMissions/ActiveMissions.tsx | 45 ++++++++++++++++++- 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/electron/events/journal.js b/electron/events/journal.js index 19bf3d8..a00ea62 100644 --- a/electron/events/journal.js +++ b/electron/events/journal.js @@ -79,6 +79,12 @@ function sortJournal() { credits: parsedEntry.Credits } break; + case 'ShipyardSwap': + journalData[fid].info = { + ...journalData[fid].info, + ship: parsedEntry.ShipType_Localised, + } + break; case 'Commander': journalData[fid].info = { ...journalData[fid].info, diff --git a/src/components/ActiveMissions/ActiveMission.scss b/src/components/ActiveMissions/ActiveMission.scss index f4cbbd7..56cb014 100644 --- a/src/components/ActiveMissions/ActiveMission.scss +++ b/src/components/ActiveMissions/ActiveMission.scss @@ -11,7 +11,6 @@ } .mission-list-item { .row-item.custom { - position: relative; progress { position: absolute; @@ -19,6 +18,11 @@ left: 0; } } + .row-item { + .expires { + color: $red; + } + } } } diff --git a/src/components/ActiveMissions/ActiveMissions.tsx b/src/components/ActiveMissions/ActiveMissions.tsx index 25e6139..33f68fd 100644 --- a/src/components/ActiveMissions/ActiveMissions.tsx +++ b/src/components/ActiveMissions/ActiveMissions.tsx @@ -1,8 +1,51 @@ import dayjs from 'dayjs'; +import duration from 'dayjs/plugin/duration'; import { formatNumber } from '../../helpers/formatNumber'; import './ActiveMission.scss'; +import { useEffect, useState } from 'react'; + +dayjs.extend(duration); function ActiveMissions({ missions }: any) { + const [time, setTime]: any = useState(""); + + const under24hour = (expiration: string) => { + const now = new Date(); + const exp = new Date(expiration); + + const diffInMs = exp.getTime() - now.getTime(); + const diffInHours = diffInMs / (1000 * 60 * 60); + + return diffInHours <= 24; + }; + + const setTimeLeft = (expiration: string) => { + const now = dayjs(); + const exp = dayjs(expiration); + + const diff = exp.diff(now); + + if(diff > 0) { + const duration = dayjs.duration(diff); + const hours = Math.floor(duration.asHours()); + const minutes = duration.minutes().toString().padStart(2, '0'); + const seconds = duration.seconds().toString().padStart(2, '0'); + + return `${hours}:${minutes}:${seconds}`; + } + } + + useEffect(() => { + const updateTimeLeft = () => { + const newTimeLeft = missions.map((mission: any) => setTimeLeft(mission.Expiry)); + setTime(newTimeLeft); + }; + + const intervalId = setInterval(updateTimeLeft, 1000); + + return () => clearInterval(intervalId); // Cleanup on unmount + }, [time]); + return (
    @@ -23,7 +66,7 @@ function ActiveMissions({ missions }: any) {
{data.DestinationStation}
{data.Commodity_Localised} ({data.Count})
-
{dayjs(data.Expiry).format('ddd, MMM D, YYYY')}
+
{dayjs(data.Expiry).format('ddd, MMM D, YYYY')} {time[index]}
{formatNumber(data.Reward)}
))} From 81f05dd70df1f11b8aaabbffd8813a09ac2cd7d5 Mon Sep 17 00:00:00 2001 From: Ajlanclos Date: Fri, 13 Sep 2024 15:08:59 -0500 Subject: [PATCH 07/12] added system to destination info --- src/components/ActiveMissions/ActiveMissions.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/components/ActiveMissions/ActiveMissions.tsx b/src/components/ActiveMissions/ActiveMissions.tsx index 33f68fd..de0c9a8 100644 --- a/src/components/ActiveMissions/ActiveMissions.tsx +++ b/src/components/ActiveMissions/ActiveMissions.tsx @@ -50,23 +50,23 @@ function ActiveMissions({ missions }: any) {
  • -
    Mission
    -
    Destination
    +
    Mission
    +
    Destination
    Commodity
    -
    Expiration
    +
    Expiration
    Payout
  • {missions.map((data: any, index: number) => (
  • -
    +
    {index + 1}{data.LocalisedName}
    -
    {data.DestinationStation}
    +
    {data.DestinationSystem} {data.DestinationStation}
    {data.Commodity_Localised} ({data.Count})
    -
    {dayjs(data.Expiry).format('ddd, MMM D, YYYY')} {time[index]}
    +
    {dayjs(data.Expiry).format('ddd, MMM D, YYYY')} {time[index]}
    {formatNumber(data.Reward)}
  • ))} From fa8b71d76e849d7c3c6332a218999f6b26b78ae2 Mon Sep 17 00:00:00 2001 From: Ajlanclos Date: Fri, 13 Sep 2024 15:11:27 -0500 Subject: [PATCH 08/12] resizing panels --- src/components/ActiveMissions/ActiveMissions.tsx | 2 +- src/components/CompleteMissions/CompleteMissions.tsx | 2 +- src/components/Config/Config.tsx | 2 +- src/pages/MissionPage.tsx | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/ActiveMissions/ActiveMissions.tsx b/src/components/ActiveMissions/ActiveMissions.tsx index de0c9a8..74f5b6b 100644 --- a/src/components/ActiveMissions/ActiveMissions.tsx +++ b/src/components/ActiveMissions/ActiveMissions.tsx @@ -47,7 +47,7 @@ function ActiveMissions({ missions }: any) { }, [time]); return ( -
    +
    • Mission
      diff --git a/src/components/CompleteMissions/CompleteMissions.tsx b/src/components/CompleteMissions/CompleteMissions.tsx index 6234223..6e40ce5 100644 --- a/src/components/CompleteMissions/CompleteMissions.tsx +++ b/src/components/CompleteMissions/CompleteMissions.tsx @@ -4,7 +4,7 @@ import './CompleteMissions.scss'; function CompleteMissions({ missions }: any) { return ( -
      +
      • Mission
        diff --git a/src/components/Config/Config.tsx b/src/components/Config/Config.tsx index 8765bba..13773b9 100644 --- a/src/components/Config/Config.tsx +++ b/src/components/Config/Config.tsx @@ -93,7 +93,7 @@ function Config() { }, []); return ( -
        +
        Commodity Config
        diff --git a/src/pages/MissionPage.tsx b/src/pages/MissionPage.tsx index d5bb631..3c6d5ef 100644 --- a/src/pages/MissionPage.tsx +++ b/src/pages/MissionPage.tsx @@ -205,7 +205,7 @@ function MissionPage() { ) : ( )} -
        +
        Date: Fri, 13 Sep 2024 22:26:59 -0500 Subject: [PATCH 09/12] working on dropdown --- src/components/CommanderTab/CommanderTab.tsx | 32 ++++++++++++-------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/components/CommanderTab/CommanderTab.tsx b/src/components/CommanderTab/CommanderTab.tsx index 634d088..0b92774 100644 --- a/src/components/CommanderTab/CommanderTab.tsx +++ b/src/components/CommanderTab/CommanderTab.tsx @@ -28,20 +28,26 @@ function CommanderTab({ commanderData }: any) {
        Choose Your Commander
        - {Object.keys(commanderData).map((key, index) => ( -
        chooseActiveCommander(key)} - > - {key === commander?.info?.fid && ( - - )} -
        {commanderData[key].info?.name}
        + {Object.keys(commanderData).length <= 5 ? ( +
        + {Object.keys(commanderData).map((key, index) => ( +
        chooseActiveCommander(key)} + > + {key === commander?.info?.fid && ( + + )} +
        {commanderData[key].info?.name}
        +
        + ))}
        - ))} + ) : ( +
        + )} +
        From abe75cb509fa8f58d07c0c19e37f02f5bc9b2246 Mon Sep 17 00:00:00 2001 From: Ajlanclos Date: Sat, 14 Sep 2024 01:27:18 -0500 Subject: [PATCH 10/12] commander tabs into dropdown --- src/components/CommanderTab/CommanderTab.tsx | 25 +++++++++- src/index.scss | 51 ++++++++++++++++++++ 2 files changed, 75 insertions(+), 1 deletion(-) diff --git a/src/components/CommanderTab/CommanderTab.tsx b/src/components/CommanderTab/CommanderTab.tsx index 0b92774..69b8364 100644 --- a/src/components/CommanderTab/CommanderTab.tsx +++ b/src/components/CommanderTab/CommanderTab.tsx @@ -1,6 +1,7 @@ import { useEffect, useState } from "react"; import "./CommanderTab.scss"; import { useCommanderState } from "../../context/Commander"; +import { Dropdown } from 'primereact/dropdown'; import dayjs from "dayjs"; function CommanderTab({ commanderData }: any) { @@ -9,6 +10,18 @@ function CommanderTab({ commanderData }: any) { const [commander, setCommander]: any = useState(null); const [time, setTime]: any = useState(dayjs().format("HH:mm:ss")); + const onDropdownChange = (e: any) => { + const { value } = e.target; + chooseActiveCommander(value); + } + + const formatOptions = () => { + return Object.keys(commanderData).map((key) => ({ + label: commanderData[key].info.name, + value: commanderData[key].info.fid + })); + } + useEffect(() => { if (!activeCommander) return; setCommander(activeCommander); @@ -21,6 +34,8 @@ function CommanderTab({ commanderData }: any) { return () => clearInterval(intervalId); }, []); + + const options = formatOptions(); return (
        @@ -45,7 +60,15 @@ function CommanderTab({ commanderData }: any) { ))}
        ) : ( -
        +
        + +
        )}
        diff --git a/src/index.scss b/src/index.scss index b373167..1ece930 100644 --- a/src/index.scss +++ b/src/index.scss @@ -168,6 +168,32 @@ button { width: 100%; } +.p-dropdown { + background: $gray-dark; + border: 1px solid $gray-light; + padding: .25rem; + &:focus { + border: 1px solid var(--accent); // Highlight border on focus + outline: none; + box-shadow: 0 0 5px rgba(var(--accent), 0.5); // Optional shadow for focus + } +} +.p-dropdown-items-wrapper { + background: $gray-dark; + border: 1px solid $gray-light; + margin-top: 5px; + .p-dropdown-item { + padding: 5px; + text-transform: uppercase; + &.p-highlight { + color: var(--accent); + } + &:hover { + background: $gray; + } + } +} + input { background: $gray-dark; border: 1px solid $gray-light; @@ -207,4 +233,29 @@ textarea { @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } +} + +::-webkit-scrollbar { + width: 14px; + height: 10px; + padding: 0 1rem; + margin: 10px; +} +/* Track */ + +::-webkit-scrollbar-track { + box-shadow: none; + background: $gray-dark; +} +/* Handle */ + +::-webkit-scrollbar-thumb { + background: $gray; + border-radius: 10px; + border: 3px solid $gray-dark; +} +/* Handle on hover */ + +::-webkit-scrollbar-thumb:hover { + // background: $blue; } \ No newline at end of file From 23721a6a6dc30c89112e4657ec1d6c9e368a9046 Mon Sep 17 00:00:00 2001 From: Ajlanclos Date: Sat, 14 Sep 2024 13:48:35 -0500 Subject: [PATCH 11/12] manual refresh button --- package.json | 2 +- src/components/CommanderTab/CommanderTab.tsx | 20 ++++----- src/components/TabMenu/TabMenu.tsx | 46 ++++++++++++++------ src/context/Commander.tsx | 1 + src/index.scss | 1 + src/pages/MissionPage.tsx | 15 ++++--- 6 files changed, 55 insertions(+), 30 deletions(-) diff --git a/package.json b/package.json index 7a9771a..eee3b02 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "TrakkrApp", "description": "An Elite Dangerous Mission Tracker Tool", "private": true, - "version": "0.1.5", + "version": "0.1.6", "author": "Dkter Roc", "main": "./electron/main.js", "homepage": "./", diff --git a/src/components/CommanderTab/CommanderTab.tsx b/src/components/CommanderTab/CommanderTab.tsx index 69b8364..b30cee9 100644 --- a/src/components/CommanderTab/CommanderTab.tsx +++ b/src/components/CommanderTab/CommanderTab.tsx @@ -1,7 +1,7 @@ import { useEffect, useState } from "react"; import "./CommanderTab.scss"; import { useCommanderState } from "../../context/Commander"; -import { Dropdown } from 'primereact/dropdown'; +import { Dropdown } from "primereact/dropdown"; import dayjs from "dayjs"; function CommanderTab({ commanderData }: any) { @@ -13,14 +13,14 @@ function CommanderTab({ commanderData }: any) { const onDropdownChange = (e: any) => { const { value } = e.target; chooseActiveCommander(value); - } + }; const formatOptions = () => { return Object.keys(commanderData).map((key) => ({ label: commanderData[key].info.name, value: commanderData[key].info.fid })); - } + }; useEffect(() => { if (!activeCommander) return; @@ -34,7 +34,7 @@ function CommanderTab({ commanderData }: any) { return () => clearInterval(intervalId); }, []); - + const options = formatOptions(); return ( @@ -44,12 +44,13 @@ function CommanderTab({ commanderData }: any) { Choose Your Commander
        {Object.keys(commanderData).length <= 5 ? ( -
        +
        {Object.keys(commanderData).map((key, index) => (
        chooseActiveCommander(key)} > {key === commander?.info?.fid && ( @@ -61,8 +62,8 @@ function CommanderTab({ commanderData }: any) {
        ) : (
        -
        )} -
        diff --git a/src/components/TabMenu/TabMenu.tsx b/src/components/TabMenu/TabMenu.tsx index 7b2cd12..6c0ec14 100644 --- a/src/components/TabMenu/TabMenu.tsx +++ b/src/components/TabMenu/TabMenu.tsx @@ -1,10 +1,17 @@ import { useEffect, useState } from "react"; import "./TabMenu.scss"; import dayjs from "dayjs"; +import { useCommanderState } from "../../context/Commander"; function TabMenu({ menuItems, onClick }: any) { + const { fetchMissionData, loading }: any = useCommanderState(); + const [selected, setSelected] = useState({}); + const onRefreshClick = () => { + fetchMissionData(); + }; + const onClickMenu = (item: any) => { setSelected(item); @@ -23,22 +30,33 @@ function TabMenu({ menuItems, onClick }: any) { : "flex align-items-center gap-2"; return ( -
        -
        - {menuItems.map((item: any, index: number) => ( - + ))} +
        +
        + - ))} +
        ); diff --git a/src/context/Commander.tsx b/src/context/Commander.tsx index c23c12a..0574d63 100644 --- a/src/context/Commander.tsx +++ b/src/context/Commander.tsx @@ -33,6 +33,7 @@ export const CommanderProvider = ({ children }: any) => { const fetchMissionData = async () => { try { + setLoading(true); const data: any = await window.electron.getMissionDetails(); console.log("fetched mission data: ", data); setMissionData(data); diff --git a/src/index.scss b/src/index.scss index 1ece930..9781677 100644 --- a/src/index.scss +++ b/src/index.scss @@ -228,6 +228,7 @@ textarea { .spin { display: inline-block; animation: spin 1s linear infinite; + transform-origin: center; } @keyframes spin { diff --git a/src/pages/MissionPage.tsx b/src/pages/MissionPage.tsx index 3c6d5ef..9e748a1 100644 --- a/src/pages/MissionPage.tsx +++ b/src/pages/MissionPage.tsx @@ -120,7 +120,7 @@ function MissionPage() { (total: number, mission: any) => total + (mission.Reward || 0), 0 ); - } + }; const calculateShareDate = () => { const allMissions = [...acceptedMissions, ...completedMissions]; @@ -194,7 +194,7 @@ function MissionPage() { }, [acceptedMissions, completedMissions]); return ( -
        +
        @@ -241,10 +241,12 @@ function MissionPage() { )}
        + > + Share Stack +
        @@ -254,7 +256,10 @@ function MissionPage() {
        )} -
        Last update: {dayjs(fetchedAt).fromNow()}
        +
        + Last update:{" "} + {dayjs(fetchedAt).fromNow()} +
        Date: Sat, 14 Sep 2024 14:01:04 -0500 Subject: [PATCH 12/12] updated readme --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4c8e03e..349359f 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ This app is in Early Development. Trakkr was designed and developed to assist Elite Dangerous Commanders who are involved in `Wing Mining Mission` operations. -Report all defects to `qore` on discord. +Join our discord for support. [Trakkr Discord](https://discord.gg/DY7kUHdtdz) GitHub Logo @@ -17,6 +17,7 @@ Report all defects to `qore` on discord. - Themes ## Download + Check the lastest release and download the .exe for use. ## Credits @@ -33,8 +34,10 @@ Tested by - AlphaLovesYou ## Contribution + All contributions should be branched from `develop` Please follow these naming conventions for branches: + - **Feature branches**: `feature/branch-name` - **Bugfix branches**: `bugfix/branch-name` - **Hotfix branches**: `hotfix/branch-name`