From acd8e7300fa3142ad069bd21f50e8123e5ae12ee Mon Sep 17 00:00:00 2001 From: xWarvan Date: Mon, 21 Jul 2025 22:29:52 +0700 Subject: [PATCH 1/5] update faction page --- src/pages/FactionPage.tsx | 458 +++++++++++++++++++------------------- 1 file changed, 228 insertions(+), 230 deletions(-) diff --git a/src/pages/FactionPage.tsx b/src/pages/FactionPage.tsx index 33c9158..3640b46 100644 --- a/src/pages/FactionPage.tsx +++ b/src/pages/FactionPage.tsx @@ -180,260 +180,258 @@ export const FactionPage: React.FC = () => { const currentFaction = factions.find(f => f.name === walletStatus?.faction); return ( -
-
-
- - {showConfetti && ( - - )} +
+
- setIsPurchaseModalOpen(false)} - onPurchase={handlePurchase} - contractName="Eternal Pass" + {showConfetti && ( + + )} -
- {/* Header Section */} -
-

Factions

- {!walletStatus?.faction && walletStatus?.isUnlocked && ( -
-

Picking Your Faction

-
-

- Important: Faction selection is final - Team players only, no team quitting! -

-
-

- Rewards Distribution: Faction rewards are split among all faction members - being in the biggest faction may not be the best strategy. -

-

- Activity Matters: The most active members will receive additional rewards, while non-active members will receive no rewards. -

-

- Reward Sources: Rewards come from multiple sources: -

-
    -
  • Partnerships
  • -
  • Premium pass sales revenue
  • -
  • In-game revenue
  • -
  • Funds raised
  • -
  • Profits from staking
  • -
+ setIsPurchaseModalOpen(false)} + onPurchase={handlePurchase} + contractName="Eternal Pass" + /> + +
+ {/* Title Section */} +
+

+ Factions +

+

+ Choose your path, earn rewards, and lead your team! +

+
+ + {/* Your Faction Section */} + {walletStatus?.faction && currentFaction && ( +
+
+ Your Faction + + CURRENT + + +
+
+ {/* Decorative highlight bar */} +
+ {/* Mascot and Info */} +
+ {currentFaction.mascot && ( +
+ {`${currentFaction.name}
+ )} +
+

{currentFaction.name}

+ {currentFaction.perks && ( +
    + {currentFaction.perks.map((perk, idx) => ( +
  • + {perk} +
  • + ))} +
+ )}
- )} - {walletStatus?.faction && currentFaction && ( -
-
-
- {currentFaction.mascot && ( - {`${currentFaction.name} - )} -
-

Your Faction

-

{currentFaction.name}

- {currentFaction.perks && ( -
-

{currentFaction.perks[0]}

-
- )} -
+
+

Daily Offerings

+

Offer praise once daily. Build streaks for RUNE rewards!

+
+
+
Your Offerings: {userOfferings?.IndividualOfferings || 0}
+
Times Fed: {walletStatus?.monster?.totalTimesFed || 0}
+
Times Played: {walletStatus?.monster?.totalTimesPlay || 0}
+
Missions: {walletStatus?.monster?.totalTimesMission || 0}
+
Total Points: {calculateUserPoints()}
- -
-
-

Daily Offerings

-

- Offer praise to the altar of your team once daily. Build streaks to earn RUNE rewards - consistency is key! -

-
-
-
-
- Your Offerings: - {userOfferings?.IndividualOfferings || 0} -
-
- Times Fed: - {walletStatus?.monster?.totalTimesFed || 0} -
-
- Times Played: - {walletStatus?.monster?.totalTimesPlay || 0} -
-
- Missions: - {walletStatus?.monster?.totalTimesMission || 0} -
-
- Total Points: - {calculateUserPoints()} -
-
-
-
- Avg Level: - {currentFaction.averageLevel ? Math.round(currentFaction.averageLevel * 10) / 10 : 0} -
-
-
Offering: {ACTIVITY_POINTS.OFFERING}pts
-
Feed: {ACTIVITY_POINTS.FEED}pt
-
Play: {ACTIVITY_POINTS.PLAY}pts
-
Mission: {ACTIVITY_POINTS.MISSION}pts
-
-
-
-
-
- - {nextOfferingTime && ( -
- Next offering in: {nextOfferingTime} -
- )} -
+
+
Avg Level: {currentFaction.averageLevel ? Math.round(currentFaction.averageLevel * 10) / 10 : 0}
+
+
Offering: {ACTIVITY_POINTS.OFFERING} pts
+
Feed: {ACTIVITY_POINTS.FEED} pt
+
Play: {ACTIVITY_POINTS.PLAY} pts
+
Mission: {ACTIVITY_POINTS.MISSION} pts
+
+ + {nextOfferingTime && ( +
+ Next offering in: {nextOfferingTime} +
+ )} +
- )} -
+
+
+ )} - {/* Loading State or Content */} + {/* Faction Selection Info (jika belum punya faksi) */} + {!walletStatus?.faction && walletStatus?.isUnlocked && ( +
+

Pick Your Faction

+
+

+ ⚠️ Faction selection is FINAL. Choose wisely! +

+
    +
  • Rewards Distribution: Shared among members. Biggest isn't always best!
  • +
  • Activity Matters: Most active get extra rewards. Inactive get none.
  • +
  • Sources: Partnerships, premium sales, in-game, fundraising, staking.
  • +
+
+
+ )} + + {/* Grid Factions Available */} +
+

Factions Available

{isInitialLoad && !factions.length ? ( -
+
- ) : factions.length > 0 && ( + ) : (
- {factions.map((faction) => ( -
navigate(`/factions/${FACTION_TO_PATH[faction.name as keyof typeof FACTION_TO_PATH]}`)} - className={`flex flex-col h-full p-2.5 rounded-xl ${theme.container} border ${theme.border} backdrop-blur-md transform transition-all duration-300 hover:scale-[1.02] hover:shadow-xl min-h-[480px] cursor-pointer`} - > -
- {faction.mascot && ( - {`${faction.name} - )} -
-
-

{faction.name}

-
-
- {faction.perks && ( -
    - {faction.perks.map((perk, index) => ( -
  • - - {perk} -
  • - ))} -
- )} -
-
-
-
- Members: - {faction.memberCount} -
-
- Monsters: - {faction.monsterCount} -
-
- Avg Level: - {faction.averageLevel ? Math.round(faction.averageLevel * 10) / 10 : 0} -
-
- Offerings: - - {offeringStats?.[faction.name as keyof OfferingStats] || 0} - -
-
-
-
- Times Fed: - {faction.totalTimesFed || 0} -
-
- Times Played: - {faction.totalTimesPlay || 0} -
-
- Missions: - {faction.totalTimesMission || 0} -
-
- Points: - {calculateFactionPoints(faction)} -
-
+ {factions + .filter(f => !walletStatus?.faction || walletStatus?.faction !== f.name) + .map((faction) => ( +
+ {/* Mascot & Info */} +
+ {faction.mascot && ( + {`${faction.name} + )} +
+
+

{faction.name}

+ {faction.perks && ( +
    + {faction.perks.map((perk, index) => ( +
  • + + {perk} +
  • + ))} +
+ )} +
+
+
Members: {faction.memberCount}
+
Monsters: {faction.monsterCount}
+
Avg Level: {faction.averageLevel ? Math.round(faction.averageLevel * 10) / 10 : 0}
+
Offerings: {offeringStats?.[faction.name as keyof OfferingStats] || 0}
+
+
+
Times Fed: {faction.totalTimesFed || 0}
+
Times Played: {faction.totalTimesPlay || 0}
+
Missions: {faction.totalTimesMission || 0}
+
Points: {calculateFactionPoints(faction)}
+
-
-
- {!walletStatus?.isUnlocked ? ( +
- ) : !walletStatus?.faction && ( - - )} - {walletStatus?.faction === faction.name && ( -
- Current Faction -
- )} + {!walletStatus?.isUnlocked ? ( + + ) : !walletStatus?.faction && ( + + )} +
-
- ))} + ))}
)} -
-
-
+
+
+
+ + {/* Custom Animations */} +
); -}; +}; \ No newline at end of file From 18500e170174c16dba3f08c8f8b0b938e22695e8 Mon Sep 17 00:00:00 2001 From: xWarvan Date: Tue, 22 Jul 2025 04:17:51 +0700 Subject: [PATCH 2/5] fix(ui): adjust layout for full-width and prevent horizontal scroll on mobile --- src/pages/FactionPage.tsx | 406 ++++++++++++++++++++++++++++---------- 1 file changed, 305 insertions(+), 101 deletions(-) diff --git a/src/pages/FactionPage.tsx b/src/pages/FactionPage.tsx index 3640b46..5cc1e72 100644 --- a/src/pages/FactionPage.tsx +++ b/src/pages/FactionPage.tsx @@ -200,9 +200,9 @@ export const FactionPage: React.FC = () => { contractName="Eternal Pass" /> -
+
{/* Title Section */} -
+

Factions

@@ -213,60 +213,46 @@ export const FactionPage: React.FC = () => { {/* Your Faction Section */} {walletStatus?.faction && currentFaction && ( -
-
- Your Faction - - CURRENT - - -
-
- {/* Decorative highlight bar */} -
- {/* Mascot and Info */} -
+
+

Your Faction

+
+
{currentFaction.mascot && ( -
- + {`${currentFaction.name}
)}
-

{currentFaction.name}

+

{currentFaction.name}

{currentFaction.perks && ( -
    +
      {currentFaction.perks.map((perk, idx) => ( -
    • - {perk} +
    • + {perk}
    • ))}
    )}
-
-

Daily Offerings

-

Offer praise once daily. Build streaks for RUNE rewards!

-
+
+

Daily Offerings

+

Offer praise once daily. Build streaks for RUNE rewards!

+
-
Your Offerings: {userOfferings?.IndividualOfferings || 0}
-
Times Fed: {walletStatus?.monster?.totalTimesFed || 0}
-
Times Played: {walletStatus?.monster?.totalTimesPlay || 0}
-
Missions: {walletStatus?.monster?.totalTimesMission || 0}
-
Total Points: {calculateUserPoints()}
+
Your Offerings: {userOfferings?.IndividualOfferings || 0}
+
Times Fed: {walletStatus?.monster?.totalTimesFed || 0}
+
Times Played: {walletStatus?.monster?.totalTimesPlay || 0}
+
Missions: {walletStatus?.monster?.totalTimesMission || 0}
+
Total Points: {calculateUserPoints()}
-
Avg Level: {currentFaction.averageLevel ? Math.round(currentFaction.averageLevel * 10) / 10 : 0}
-
+
Avg Level: {currentFaction.averageLevel ? Math.round(currentFaction.averageLevel * 10) / 10 : 0}
+
Offering: {ACTIVITY_POINTS.OFFERING} pts
Feed: {ACTIVITY_POINTS.FEED} pt
Play: {ACTIVITY_POINTS.PLAY} pts
@@ -274,28 +260,38 @@ export const FactionPage: React.FC = () => {
-
+
{nextOfferingTime && ( -
- Next offering in: {nextOfferingTime} +
+ Next offering in: {nextOfferingTime}
)}
+
+ +
)} - {/* Faction Selection Info (jika belum punya faksi) */} + {/* Faction Selection Info (if no faction is selected yet) */} {!walletStatus?.faction && walletStatus?.isUnlocked && ( -
-

Pick Your Faction

-
-

+

+

Pick Your Faction

+
+

⚠️ Faction selection is FINAL. Choose wisely!

-
    +
    • Rewards Distribution: Shared among members. Biggest isn't always best!
    • Activity Matters: Most active get extra rewards. Inactive get none.
    • Sources: Partnerships, premium sales, in-game, fundraising, staking.
    • @@ -304,73 +300,69 @@ export const FactionPage: React.FC = () => {
)} - {/* Grid Factions Available */} -
-

Factions Available

+ {/* Grid Factions Opposing */} +
+

Opposing Factions

{isInitialLoad && !factions.length ? ( -
+
) : ( -
+
{factions .filter(f => !walletStatus?.faction || walletStatus?.faction !== f.name) .map((faction) => (
- {/* Mascot & Info */} -
+
{faction.mascot && ( {`${faction.name} )}
-
-

{faction.name}

+
+

{faction.name}

{faction.perks && ( -
    +
      {faction.perks.map((perk, index) => ( -
    • - +
    • + {perk}
    • ))}
    )} -
    +
    -
    Members: {faction.memberCount}
    -
    Monsters: {faction.monsterCount}
    -
    Avg Level: {faction.averageLevel ? Math.round(faction.averageLevel * 10) / 10 : 0}
    -
    Offerings: {offeringStats?.[faction.name as keyof OfferingStats] || 0}
    +
    Members: {faction.memberCount}
    +
    Monsters: {faction.monsterCount}
    +
    Avg Level: {faction.averageLevel ? Math.round(faction.averageLevel * 10) / 10 : 0}
    +
    Offerings: {offeringStats?.[faction.name as keyof OfferingStats] || 0}
    -
    Times Fed: {faction.totalTimesFed || 0}
    -
    Times Played: {faction.totalTimesPlay || 0}
    -
    Missions: {faction.totalTimesMission || 0}
    -
    Points: {calculateFactionPoints(faction)}
    +
    Times Fed: {faction.totalTimesFed || 0}
    +
    Times Played: {faction.totalTimesPlay || 0}
    +
    Missions: {faction.totalTimesMission || 0}
    +
    Points: {calculateFactionPoints(faction)}
    -
    +
    {!walletStatus?.isUnlocked ? ( @@ -378,7 +370,7 @@ export const FactionPage: React.FC = () => { @@ -392,8 +384,243 @@ export const FactionPage: React.FC = () => {
- {/* Custom Animations */} + {/* Custom Animations & Styles */}
); From b6c4defb6b695bab1de2752753aa21dee693a37f Mon Sep 17 00:00:00 2001 From: xWarvan Date: Tue, 22 Jul 2025 23:52:16 +0700 Subject: [PATCH 3/5] refactor: apply max-width, remove scrollbars --- src/pages/FactionPage.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/FactionPage.tsx b/src/pages/FactionPage.tsx index 5cc1e72..47c5f2f 100644 --- a/src/pages/FactionPage.tsx +++ b/src/pages/FactionPage.tsx @@ -200,7 +200,7 @@ export const FactionPage: React.FC = () => { contractName="Eternal Pass" /> -
+
{/* Title Section */}

@@ -388,8 +388,8 @@ export const FactionPage: React.FC = () => {

From 85ef518361e846c61a433c42f847343054258e03 Mon Sep 17 00:00:00 2001 From: xWarvan Date: Sat, 26 Jul 2025 06:50:52 +0700 Subject: [PATCH 5/5] done --- src/pages/FactionPage.tsx | 454 +++++++++++++++++++++++--------------- 1 file changed, 279 insertions(+), 175 deletions(-) diff --git a/src/pages/FactionPage.tsx b/src/pages/FactionPage.tsx index b196a53..865c10c 100644 --- a/src/pages/FactionPage.tsx +++ b/src/pages/FactionPage.tsx @@ -182,12 +182,16 @@ export const FactionPage: React.FC = () => { return offeringPoints + feedPoints + playPoints + missionPoints; }; - const currentFaction = sortedFactions.find((f) => f.name === walletStatus?.faction); + const currentFaction = sortedFactions.find( + (f) => f.name === walletStatus?.faction + ); return (
{/* Header */} -
+
+
+
{showConfetti && ( {

- Important: Faction selection is final - Team players only, no team - quitting! + Important: Faction selection is final - Team players only, no + team quitting!

@@ -273,11 +277,13 @@ export const FactionPage: React.FC = () => {

Your Faction

- + {/* Faction Hero Section */} -
+
- {/* Gambar Mascot Besar */} + {/* Image */}
{currentFaction.mascot && ( { )}
- {/* Konten Teks */} + {/* Teks */}
-

+

{currentFaction.name}

{currentFaction.perks && ( @@ -300,28 +308,51 @@ export const FactionPage: React.FC = () => {

)}
- + {/* Mini Stats */}
-

Members

-

{Number(currentFaction.memberCount || 0)}

+

+ Members +

+

+ {Number(currentFaction.memberCount || 0)} +

-

Avg Level

+

+ Avg Level +

{currentFaction.averageLevel?.toFixed(1)}

-

Points

+

+ Points +

{calculateFactionPoints(currentFaction)}

-

Rank

-

#{sortedFactions.findIndex(f => f.name === currentFaction.name) + 1}

+

+ Rank +

+

+ # + {sortedFactions.findIndex( + (f) => f.name === currentFaction.name + ) + 1} +

@@ -330,69 +361,110 @@ export const FactionPage: React.FC = () => { {/* User Stats Section */}
-

Your Contribution

-
+

+ Your Contribution +

+
Offerings - {userOfferings?.IndividualOfferings || 0} + + {userOfferings?.IndividualOfferings || 0} +
-
- +
Times Fed - {walletStatus?.monster?.totalTimesFed || 0} + + {walletStatus?.monster?.totalTimesFed || 0} +
-
- +
Times Played - {walletStatus?.monster?.totalTimesPlay || 0} + + {walletStatus?.monster?.totalTimesPlay || 0} +
-
- +
Missions - {walletStatus?.monster?.totalTimesMission || 0} + + {walletStatus?.monster?.totalTimesMission || 0} +
-
- + {/* Total Points */}
- Total Points - {calculateUserPoints()} + + Total Points + + + {calculateUserPoints()} +
@@ -409,138 +481,159 @@ export const FactionPage: React.FC = () => { {sortedFactions.length - 1} opponents
- +
{sortedFactions - .filter(f => f.name !== walletStatus?.faction) + .filter((f) => f.name !== walletStatus?.faction) .map((faction) => ( -
- navigate( - `/factions/${ - FACTION_TO_PATH[ - faction.name as keyof typeof FACTION_TO_PATH - ] - }` - ) - } - className={`p-4 rounded-xl ${theme.container} border ${theme.border} backdrop-blur-md hover:scale-[1.01] hover:shadow-lg cursor-pointer transition-all duration-200 mb-4`} - > -
- {/* Gambar Mascot Besar */} - {faction.mascot && ( -
- {`${faction.name} -
- )} - -
-
-

- {faction.name} -

- - #{sortedFactions.findIndex(f => f.name === faction.name) + 1} - -
- - {/* Stats Grid */} -
-
-
- Members: - - {faction.memberCount} - -
+
+ navigate( + `/factions/${ + FACTION_TO_PATH[ + faction.name as keyof typeof FACTION_TO_PATH + ] + }` + ) + } + className={`p-4 rounded-xl ${theme.container} border ${theme.border} backdrop-blur-md hover:scale-[1.01] hover:shadow-lg cursor-pointer transition-all duration-200 mb-4`} + > +
+ {/* Image */} + {faction.mascot && ( +
+ {`${faction.name}
- -
-
- Avg Level: - - {faction.averageLevel?.toFixed(1)} - -
+ )} + +
+
+

+ {faction.name} +

+ + # + {sortedFactions.findIndex( + (f) => f.name === faction.name + ) + 1} +
- -
-
- Points: - - {calculateFactionPoints(faction)} - + + {/* Stats Grid */} +
+
+
+ Members: + + {faction.memberCount} + +
-
- -
-
- Offerings: - - {offeringStats?.[faction.name as keyof OfferingStats] || 0} - + +
+
+ Avg Level: + + {faction.averageLevel?.toFixed(1)} + +
-
- -
-
- Fed: - - {faction.totalTimesFed || 0} - + +
+
+ Points: + + {calculateFactionPoints(faction)} + +
-
- -
-
- Played: - - {faction.totalTimesPlay || 0} - + +
+
+ Offerings: + + {offeringStats?.[ + faction.name as keyof OfferingStats + ] || 0} + +
-
- -
-
- Missions: - - {faction.totalTimesMission || 0} - + +
+
+ Fed: + + {faction.totalTimesFed || 0} + +
-
- -
-
- Activity: - { - (() => { - const members = Number(faction.memberCount || 0); - const activity = Number((faction as any).totalActivity || 0); - return members > 0 ? Math.round(activity / members) : 0; - })() - } + +
+
+ Played: + + {faction.totalTimesPlay || 0} + +
+
+ +
+
+ Missions: + + {faction.totalTimesMission || 0} + +
+
+ +
+
+ Activity: + + {(() => { + const members = Number( + faction.memberCount || 0 + ); + const activity = Number( + (faction as any).totalActivity || 0 + ); + return members > 0 + ? Math.round(activity / members) + : 0; + })()} + +
+ + {/* Perks */} + {faction.perks && faction.perks.length > 0 && ( +
+

+ Faction Perks: +

+

+ {faction.perks[0]} +

+
+ )}
- - {/* Perks */} - {faction.perks && faction.perks.length > 0 && ( -
-

Faction Perks:

-

- {faction.perks[0]} -

-
- )}
-
- ))} + ))}
@@ -561,7 +654,7 @@ export const FactionPage: React.FC = () => {

Choose Your Faction

- +
{sortedFactions.map((faction) => (
{ } className={`flex flex-col h-full rounded-xl ${theme.container} border ${theme.border} backdrop-blur-md hover:scale-[1.02] hover:shadow-lg transition-all duration-300 cursor-pointer overflow-hidden`} > - {/* Gambar Mascot Besar */} + {/* Image */}
{faction.mascot && ( {
-

+

{faction.name}

- - #{sortedFactions.findIndex(f => f.name === faction.name) + 1} + + # + {sortedFactions.findIndex( + (f) => f.name === faction.name + ) + 1}
@@ -605,7 +705,9 @@ export const FactionPage: React.FC = () => { key={index} className={`flex items-start ${theme.cardText}`} > - + + • + {perk} ))} @@ -613,7 +715,9 @@ export const FactionPage: React.FC = () => { )} {/* Stats Grid */} -
+
Members: @@ -622,7 +726,7 @@ export const FactionPage: React.FC = () => {
- +
Level: @@ -631,7 +735,7 @@ export const FactionPage: React.FC = () => {
- +
Points: @@ -640,7 +744,7 @@ export const FactionPage: React.FC = () => {
- +
Offerings: @@ -675,9 +779,7 @@ export const FactionPage: React.FC = () => { className={`w-full px-3 py-2 rounded-lg font-bold ${ theme.buttonBg } hover:opacity-90 ${theme.text} ${ - isLoading - ? "opacity-60 cursor-wait" - : "" + isLoading ? "opacity-60 cursor-wait" : "" } transition-opacity`} > {isLoading ? "Joining..." : "Join Faction"} @@ -694,17 +796,19 @@ export const FactionPage: React.FC = () => { ) )}
- + {/* Footer */} -
- +
+
+
+
); -}; \ No newline at end of file +};