dev #1
					 1 changed files with 149 additions and 143 deletions
				
			
		|  | @ -751,7 +751,8 @@ export default function Page() { | ||||||
|   }, [categories]); |   }, [categories]); | ||||||
| 
 | 
 | ||||||
| function formatTrophies(value: number) { | function formatTrophies(value: number) { | ||||||
|   const sign = value > 0 ? '+' : ''; |   const sign = value > 0 ? '' : '+'; | ||||||
|  |    | ||||||
|   return `${sign}${value} trophies`; |   return `${sign}${value} trophies`; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1117,30 +1118,31 @@ function summarizeProfileDefenses(defenses: ProfileDefense[]): Summary { | ||||||
|               <details> |               <details> | ||||||
|                 <summary><h3>Existing Categories</h3></summary> |                 <summary><h3>Existing Categories</h3></summary> | ||||||
|                 <ul className="list compact"> |                 <ul className="list compact"> | ||||||
|                 {categories.length ? ( |                   {categories.length ? ( | ||||||
|                   categories.map((category) => ( |                     categories.map((category) => ( | ||||||
|                     <li key={category.id} className="list-item"> |                       <li key={category.id} className="list-item"> | ||||||
|                       <div className="defense-header"> |                         <div className="defense-header"> | ||||||
|                         <span>{category.name}</span> |                           <span>{category.name}</span> | ||||||
|                         <div className="defense-meta"> |                           <div className="defense-meta"> | ||||||
|                           <button |                             <button | ||||||
|                             type="button" |                               type="button" | ||||||
|                             className="ghost small" |                               className="ghost small" | ||||||
|                             onClick={() => handleDeleteCategory(category.id)} |                               onClick={() => handleDeleteCategory(category.id)} | ||||||
|                           > |                             > | ||||||
|                             Delete |                               Delete | ||||||
|                           </button> |                             </button> | ||||||
|  |                           </div> | ||||||
|                         </div> |                         </div> | ||||||
|                       </div> |                         <div className="defense-meta"> | ||||||
|                       <div className="defense-meta"> |                           <span>{new Date(category.createdAt).toLocaleDateString()}</span> | ||||||
|                         <span>{new Date(category.createdAt).toLocaleDateString()}</span> |                         </div> | ||||||
|                       </div> |                       </li> | ||||||
|                     </li> |                     )) | ||||||
|                   )) |                   ) : ( | ||||||
|                 ) : ( |                     <li>No categories yet.</li> | ||||||
|                   <li>No categories yet.</li> |                   )} | ||||||
|                 )} |                 </ul> | ||||||
|               </ul> |               </details> | ||||||
|             </div> |             </div> | ||||||
|           </div> |           </div> | ||||||
|           <div className="card"> |           <div className="card"> | ||||||
|  | @ -1202,40 +1204,41 @@ function summarizeProfileDefenses(defenses: ProfileDefense[]): Summary { | ||||||
|               <details> |               <details> | ||||||
|                 <summary><h3>Manage Bases</h3></summary> |                 <summary><h3>Manage Bases</h3></summary> | ||||||
|                 <ul className="list compact"> |                 <ul className="list compact"> | ||||||
|                 {bases.length ? ( |                   {bases.length ? ( | ||||||
|                   bases.map((base) => ( |                     bases.map((base) => ( | ||||||
|                     <li key={base.id} className="list-item"> |                       <li key={base.id} className="list-item"> | ||||||
|                       <div className="defense-header"> |                         <div className="defense-header"> | ||||||
|                         <div> |                           <div> | ||||||
|                           <strong>{base.title}</strong>{' '} |                             <strong>{base.title}</strong>{' '} | ||||||
|                           {base.isPrivate ? <span className="badge muted">Private</span> : null} |                             {base.isPrivate ? <span className="badge muted">Private</span> : null} | ||||||
|  |                           </div> | ||||||
|  |                           <div className="defense-meta"> | ||||||
|  |                             <button | ||||||
|  |                               type="button" | ||||||
|  |                               className="ghost small" | ||||||
|  |                               onClick={() => startEditingBase(base.id)} | ||||||
|  |                             > | ||||||
|  |                               Edit | ||||||
|  |                             </button> | ||||||
|  |                             <button | ||||||
|  |                               type="button" | ||||||
|  |                               className="ghost small" | ||||||
|  |                               onClick={() => handleDeleteBase(base.id)} | ||||||
|  |                             > | ||||||
|  |                               Delete | ||||||
|  |                             </button> | ||||||
|  |                           </div> | ||||||
|                         </div> |                         </div> | ||||||
|                         <div className="defense-meta"> |                         <div className="defense-meta"> | ||||||
|                           <button |                           <span>{new Date(base.createdAt).toLocaleDateString()}</span> | ||||||
|                             type="button" |  | ||||||
|                             className="ghost small" |  | ||||||
|                             onClick={() => startEditingBase(base.id)} |  | ||||||
|                           > |  | ||||||
|                             Edit |  | ||||||
|                           </button> |  | ||||||
|                           <button |  | ||||||
|                             type="button" |  | ||||||
|                             className="ghost small" |  | ||||||
|                             onClick={() => handleDeleteBase(base.id)} |  | ||||||
|                           > |  | ||||||
|                             Delete |  | ||||||
|                           </button> |  | ||||||
|                         </div> |                         </div> | ||||||
|                       </div> |                       </li> | ||||||
|                       <div className="defense-meta"> |                     )) | ||||||
|                         <span>{new Date(base.createdAt).toLocaleDateString()}</span> |                   ) : ( | ||||||
|                       </div> |                     <li>No bases yet.</li> | ||||||
|                     </li> |                   )} | ||||||
|                   )) |                 </ul> | ||||||
|                 ) : ( |               </details> | ||||||
|                   <li>No bases yet.</li> |  | ||||||
|                 )} |  | ||||||
|               </ul> |  | ||||||
|             </div> |             </div> | ||||||
|             {baseBeingEdited && ( |             {baseBeingEdited && ( | ||||||
|               <div className="subsection"> |               <div className="subsection"> | ||||||
|  | @ -1396,50 +1399,51 @@ function summarizeProfileDefenses(defenses: ProfileDefense[]): Summary { | ||||||
|               <details> |               <details> | ||||||
|                 <summary><h3>Manage Attacks</h3></summary> |                 <summary><h3>Manage Attacks</h3></summary> | ||||||
|                 <ul className="list compact"> |                 <ul className="list compact"> | ||||||
|                 {defenses.length ? ( |                   {defenses.length ? ( | ||||||
|                   defenses.slice(0, 10).map((defense) => { |                     defenses.slice(0, 10).map((defense) => { | ||||||
|                     const categoryName = |                       const categoryName = | ||||||
|                       categoryNameMap.get(defense.armyCategoryId) || defense.categoryName || '(No category)'; |                         categoryNameMap.get(defense.armyCategoryId) || defense.categoryName || '(No category)'; | ||||||
|                     return ( |                       return ( | ||||||
|                       <li key={defense.id} className="list-item"> |                         <li key={defense.id} className="list-item"> | ||||||
|                         <div className="defense-header"> |                           <div className="defense-header"> | ||||||
|                           <div> |                             <div> | ||||||
|                             <strong>{defense.baseTitle}</strong>{' '} |                               <strong>{defense.baseTitle}</strong>{' '} | ||||||
|                             <span className="badge">{categoryName}</span> |                               <span className="badge">{categoryName}</span> | ||||||
|  |                             </div> | ||||||
|  |                             <div className="defense-meta"> | ||||||
|  |                               <button | ||||||
|  |                                 type="button" | ||||||
|  |                                 className="ghost small" | ||||||
|  |                                 onClick={() => startEditingDefense(defense.id)} | ||||||
|  |                               > | ||||||
|  |                                 Edit | ||||||
|  |                               </button> | ||||||
|  |                               <button | ||||||
|  |                                 type="button" | ||||||
|  |                                 className="ghost small" | ||||||
|  |                                 onClick={() => handleDeleteDefense(defense.id)} | ||||||
|  |                               > | ||||||
|  |                                 Delete | ||||||
|  |                               </button> | ||||||
|  |                             </div> | ||||||
|                           </div> |                           </div> | ||||||
|                           <div className="defense-meta"> |                           <div className="defense-meta"> | ||||||
|                             <button |                             <span>{defense.stars}★</span> | ||||||
|                               type="button" |                             <span>{defense.percent}%</span> | ||||||
|                               className="ghost small" |                             <span>{formatTrophies(defense.trophies)}</span> | ||||||
|                               onClick={() => startEditingDefense(defense.id)} |                             <span>{new Date(defense.createdAt).toLocaleString()}</span> | ||||||
|                             > |  | ||||||
|                               Edit |  | ||||||
|                             </button> |  | ||||||
|                             <button |  | ||||||
|                               type="button" |  | ||||||
|                               className="ghost small" |  | ||||||
|                               onClick={() => handleDeleteDefense(defense.id)} |  | ||||||
|                             > |  | ||||||
|                               Delete |  | ||||||
|                             </button> |  | ||||||
|                           </div> |                           </div> | ||||||
|                         </div> |                         </li> | ||||||
|                         <div className="defense-meta"> |                       ); | ||||||
|                           <span>{defense.stars}★</span> |                     }) | ||||||
|                           <span>{defense.percent}%</span> |                   ) : ( | ||||||
|                           <span>{formatTrophies(defense.trophies)}</span> |                     <li>No attacks logged yet.</li> | ||||||
|                           <span>{new Date(defense.createdAt).toLocaleString()}</span> |                   )} | ||||||
|                         </div> |                 </ul> | ||||||
|                       </li> |                 {defenses.length > 10 ? ( | ||||||
|                     ); |                   <p className="muted">Showing the latest 10 entries.</p> | ||||||
|                   }) |                 ) : null} | ||||||
|                 ) : ( |               </details> | ||||||
|                   <li>No attacks logged yet.</li> |  | ||||||
|                 )} |  | ||||||
|               </ul> |  | ||||||
|               {defenses.length > 10 ? ( |  | ||||||
|                 <p className="muted">Showing the latest 10 entries.</p> |  | ||||||
|               ) : null} |  | ||||||
|             </div> |             </div> | ||||||
|             {defenseBeingEdited && ( |             {defenseBeingEdited && ( | ||||||
|               <div className="subsection"> |               <div className="subsection"> | ||||||
|  | @ -1710,28 +1714,29 @@ function summarizeProfileDefenses(defenses: ProfileDefense[]): Summary { | ||||||
|             <details open> |             <details open> | ||||||
|               <summary><h3>Army Categories vs This Base</h3></summary> |               <summary><h3>Army Categories vs This Base</h3></summary> | ||||||
|               <ul id="base-detail-categories" className="list"> |               <ul id="base-detail-categories" className="list"> | ||||||
|               {baseDetail && baseDetail.categories.length ? ( |                 {baseDetail && baseDetail.categories.length ? ( | ||||||
|                 baseDetail.categories.map((category) => ( |                   baseDetail.categories.map((category) => ( | ||||||
|                   <li |                     <li | ||||||
|                     key={category.categoryId} |                       key={category.categoryId} | ||||||
|                     className="list-item clickable" |                       className="list-item clickable" | ||||||
|                     onClick={() => openCategoryDetail(category.categoryId)} |                       onClick={() => openCategoryDetail(category.categoryId)} | ||||||
|                   > |                     > | ||||||
|                     <div className="defense-header"> |                       <div className="defense-header"> | ||||||
|                       <strong>{category.name}</strong> |                         <strong>{category.name}</strong> | ||||||
|                       <span className="badge">{category.count} attacks</span> |                         <span className="badge">{category.count} attacks</span> | ||||||
|                     </div> |                       </div> | ||||||
|                     <div className="defense-meta"> |                       <div className="defense-meta"> | ||||||
|                       <span>{category.averageStars}★ avg</span> |                         <span>{category.averageStars}★ avg</span> | ||||||
|                       <span>{category.averagePercent}% avg</span> |                         <span>{category.averagePercent}% avg</span> | ||||||
|                       <span>{formatTrophies(category.averageTrophies)} avg</span> |                         <span>{formatTrophies(category.averageTrophies)} avg</span> | ||||||
|                     </div> |                       </div> | ||||||
|                   </li> |                     </li> | ||||||
|                 )) |                   )) | ||||||
|               ) : ( |                 ) : ( | ||||||
|                 <li>No army categories have attacked this base yet.</li> |                   <li>No army categories have attacked this base yet.</li> | ||||||
|               )} |                 )} | ||||||
|             </ul> |               </ul> | ||||||
|  |             </details> | ||||||
|           </div> |           </div> | ||||||
|           <div className="card"> |           <div className="card"> | ||||||
|             <details open> |             <details open> | ||||||
|  | @ -1776,30 +1781,31 @@ function summarizeProfileDefenses(defenses: ProfileDefense[]): Summary { | ||||||
|             <details open> |             <details open> | ||||||
|               <summary><h3>Defenses</h3></summary> |               <summary><h3>Defenses</h3></summary> | ||||||
|               <ul id="base-detail-defenses" className="list"> |               <ul id="base-detail-defenses" className="list"> | ||||||
|               {defenses.filter((defense) => defense.baseId === selectedBaseId).length ? ( |                 {defenses.filter((defense) => defense.baseId === selectedBaseId).length ? ( | ||||||
|                 defenses |                   defenses | ||||||
|                   .filter((defense) => defense.baseId === selectedBaseId) |                     .filter((defense) => defense.baseId === selectedBaseId) | ||||||
|                   .map((defense) => { |                     .map((defense) => { | ||||||
|                     const date = new Date(defense.createdAt); |                       const date = new Date(defense.createdAt); | ||||||
|                     const categoryName = categoryNameMap.get(defense.armyCategoryId) || '(No category)'; |                       const categoryName = categoryNameMap.get(defense.armyCategoryId) || '(No category)'; | ||||||
|                     return ( |                       return ( | ||||||
|                       <li key={defense.id} className="list-item"> |                         <li key={defense.id} className="list-item"> | ||||||
|                         <div className="defense-header"> |                           <div className="defense-header"> | ||||||
|                           <strong>{categoryName}</strong> |                             <strong>{categoryName}</strong> | ||||||
|                           <div> |                             <div> | ||||||
|                             <strong>{defense.stars}★</strong> • {defense.percent}% • {formatTrophies(defense.trophies)} |                               <strong>{defense.stars}★</strong> • {defense.percent}% • {formatTrophies(defense.trophies)} | ||||||
|  |                             </div> | ||||||
|                           </div> |                           </div> | ||||||
|                         </div> |                           <div className="defense-meta"> | ||||||
|                         <div className="defense-meta"> |                             <span>{date.toLocaleString()}</span> | ||||||
|                           <span>{date.toLocaleString()}</span> |                           </div> | ||||||
|                         </div> |                         </li> | ||||||
|                       </li> |                       ); | ||||||
|                     ); |                     }) | ||||||
|                   }) |                 ) : ( | ||||||
|               ) : ( |                   <li>No defenses recorded for this base yet.</li> | ||||||
|                 <li>No defenses recorded for this base yet.</li> |                 )} | ||||||
|               )} |               </ul> | ||||||
|             </ul> |             </details> | ||||||
|           </div> |           </div> | ||||||
|         </section> |         </section> | ||||||
| 
 | 
 | ||||||
|  | @ -1888,7 +1894,7 @@ function summarizeProfileDefenses(defenses: ProfileDefense[]): Summary { | ||||||
|                 </ul> |                 </ul> | ||||||
|               </div> |               </div> | ||||||
|               <div className="card"> |               <div className="card"> | ||||||
|                 <details> |                 <details open> | ||||||
|                   <summary><h3>Recent Resets</h3></summary> |                   <summary><h3>Recent Resets</h3></summary> | ||||||
|                   <ul className="list compact"> |                   <ul className="list compact"> | ||||||
|                     {profileSelectedBase.trophyResets.length ? ( |                     {profileSelectedBase.trophyResets.length ? ( | ||||||
|  | @ -1897,7 +1903,7 @@ function summarizeProfileDefenses(defenses: ProfileDefense[]): Summary { | ||||||
|                           <div className="defense-header"> |                           <div className="defense-header"> | ||||||
|                             <span>{new Date(reset.date).toLocaleDateString()}</span> |                             <span>{new Date(reset.date).toLocaleDateString()}</span> | ||||||
|                             <div className="defense-meta"> |                             <div className="defense-meta"> | ||||||
|                               <span>{reset.trophiesAtStart} trophies </span> |                               <span>{reset.trophiesAtStart} trophies at start</span> | ||||||
|                               <span>{formatTrophies(reset.trophiesLost)} lost</span> |                               <span>{formatTrophies(reset.trophiesLost)} lost</span> | ||||||
|                               <span>{reset.numberOfDefenses} defenses</span> |                               <span>{reset.numberOfDefenses} defenses</span> | ||||||
|                             </div> |                             </div> | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue