LaptopCardComponent.razor 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. @using RackPeek.Domain.Resources.Hardware.Laptops
  2. @using RackPeek.Domain.Resources.Hardware.Laptops.Cpus
  3. @using RackPeek.Domain.Resources.Hardware.Laptops.Drives
  4. @using RackPeek.Domain.Resources.Hardware.Laptops.Gpus
  5. @using RackPeek.Domain.Resources.Models
  6. @inject GetLaptopUseCase GetLaptopUseCase
  7. @inject UpdateLaptopUseCase UpdateLaptopUseCase
  8. @inject DeleteLaptopUseCase DeleteLaptopUseCase
  9. @inject AddLaptopCpuUseCase AddCpuUseCase
  10. @inject UpdateLaptopCpuUseCase UpdateCpuUseCase
  11. @inject RemoveLaptopCpuUseCase RemoveCpuUseCase
  12. @inject AddLaptopDriveUseCase AddDriveUseCase
  13. @inject UpdateLaptopDriveUseCase UpdateDriveUseCase
  14. @inject RemoveLaptopDriveUseCase RemoveDriveUseCase
  15. @inject AddLaptopGpuUseCase AddGpuUseCase
  16. @inject UpdateLaptopGpuUseCase UpdateGpuUseCase
  17. @inject RemoveLaptopGpuUseCase RemoveGpuUseCase
  18. <div class="border border-zinc-800 rounded p-4 bg-zinc-900">
  19. <div class="flex justify-between items-center mb-3">
  20. <div class="text-zinc-100 hover:text-emerald-300">
  21. <NavLink href="@($"/resources/hardware/{Laptop.Name}")" class="block">
  22. @Laptop.Name
  23. </NavLink>
  24. </div>
  25. <div class="flex justify-between items-center mb-3">
  26. @if (!string.IsNullOrWhiteSpace(Laptop.Model))
  27. {
  28. <span class="text-xs text-zinc-400">
  29. @Laptop.Model
  30. </span>
  31. }
  32. <div class="flex items-center gap-2">
  33. <button
  34. class="text-xs text-red-400 hover:text-red-300 transition"
  35. title="Delete server"
  36. @onclick="ConfirmDelete">
  37. Delete
  38. </button>
  39. </div>
  40. </div>
  41. </div>
  42. <div class="grid grid-cols-1 md:grid-cols-2 gap-3 text-sm">
  43. <!-- CPU -->
  44. <div>
  45. <div class="flex items-center justify-between mb-1 group">
  46. <div class="text-zinc-400">
  47. CPU
  48. <button
  49. class="hover:text-emerald-400 transition"
  50. title="Add CPU"
  51. @onclick="OpenAddCpu">
  52. +
  53. </button>
  54. </div>
  55. </div>
  56. @if (Laptop.Cpus?.Any() == true)
  57. {
  58. @foreach (var cpu in Laptop.Cpus)
  59. {
  60. <div
  61. class="flex items-center justify-between text-zinc-300 group hover:bg-zinc-800/40 rounded px-1 py-0.5">
  62. <button
  63. class="hover:text-emerald-400"
  64. title="Edit CPU"
  65. @onclick="() => OpenEditCpu(cpu)">
  66. @cpu.Model — @cpu.Cores cores / @cpu.Threads threads
  67. </button>
  68. </div>
  69. }
  70. }
  71. </div>
  72. <!-- RAM -->
  73. <div>
  74. <div class="text-zinc-400 mb-1">
  75. RAM
  76. <button
  77. class="hover:text-emerald-400 transition"
  78. title="Edit RAM"
  79. @onclick="EditRam">
  80. +
  81. </button>
  82. </div>
  83. @if (Laptop.Ram is not null)
  84. {
  85. <div
  86. class="flex items-center justify-between text-zinc-300 group hover:bg-zinc-800/40 rounded px-1 py-0.5">
  87. <button
  88. class="hover:text-emerald-400"
  89. @onclick="EditRam">
  90. @($"{Laptop.Ram.Size} GB {Laptop.Ram.Mts} MT/s")
  91. </button>
  92. </div>
  93. }
  94. </div>
  95. <!-- Drives -->
  96. <div>
  97. <div class="flex items-center justify-between mb-1 group">
  98. <div class="text-zinc-400">
  99. Drives
  100. <button
  101. class="hover:text-emerald-400 transition"
  102. title="Add Drive"
  103. @onclick="OpenAddDrive">
  104. +
  105. </button>
  106. </div>
  107. </div>
  108. @if (Laptop.Drives?.Any() == true)
  109. {
  110. @foreach (var drive in Laptop.Drives)
  111. {
  112. <div
  113. class="flex items-center justify-between text-zinc-300 group hover:bg-zinc-800/40 rounded px-1 py-0.5">
  114. <button
  115. class="hover:text-emerald-400"
  116. @onclick="() => OpenEditDrive(drive)">
  117. @drive.Type — @drive.Size GB
  118. </button>
  119. </div>
  120. }
  121. }
  122. </div>
  123. <!-- GPUs -->
  124. <div>
  125. <div class="flex items-center justify-between mb-1 group">
  126. <div class="text-zinc-400">
  127. GPUs
  128. <button
  129. class="hover:text-emerald-400 transition"
  130. title="Add GPU"
  131. @onclick="OpenAddGpu">
  132. +
  133. </button>
  134. </div>
  135. </div>
  136. @if (Laptop.Gpus?.Any() == true)
  137. {
  138. @foreach (var gpu in Laptop.Gpus)
  139. {
  140. <div
  141. class="flex items-center justify-between text-zinc-300 group hover:bg-zinc-800/40 rounded px-1 py-0.5">
  142. <button
  143. class="hover:text-emerald-400"
  144. @onclick="() => OpenEditGpu(gpu)">
  145. @gpu.Model — @gpu.Vram GB VRAM
  146. </button>
  147. </div>
  148. }
  149. }
  150. </div>
  151. </div>
  152. </div>
  153. <CpuModal
  154. IsOpen="@_cpuModalOpen"
  155. IsOpenChanged="v => _cpuModalOpen = v"
  156. Value="@_editingCpu"
  157. OnSubmit="HandleCpuSubmit"
  158. OnDelete="HandleCpuDelete"/>
  159. <RamModal
  160. IsOpen="@_isRamModalOpen"
  161. IsOpenChanged="v => _isRamModalOpen = v"
  162. Value="@Laptop.Ram"
  163. OnSubmit="HandleRamSubmit"/>
  164. <DriveModal
  165. IsOpen="@_driveModalOpen"
  166. IsOpenChanged="v => _driveModalOpen = v"
  167. Value="@_editingDrive"
  168. OnSubmit="HandleDriveSubmit"
  169. OnDelete="HandleDriveDelete"/>
  170. <GpuModal
  171. IsOpen="@_gpuModalOpen"
  172. IsOpenChanged="v => _gpuModalOpen = v"
  173. Value="@_editingGpu"
  174. OnSubmit="HandleGpuSubmit"
  175. OnDelete="HandleGpuDelete"/>
  176. <ConfirmModal
  177. IsOpen="_confirmDeleteOpen"
  178. IsOpenChanged="v => _confirmDeleteOpen = v"
  179. Title="Delete server"
  180. ConfirmText="Delete"
  181. ConfirmClass="bg-red-600 hover:bg-red-500"
  182. OnConfirm="DeleteServer">
  183. Are you sure you want to delete <strong>@Laptop.Name</strong>?
  184. <br/>
  185. This will detach all dependent systems.
  186. </ConfirmModal>
  187. @code {
  188. [Parameter] [EditorRequired] public Laptop Laptop { get; set; } = default!;
  189. #region RAM
  190. private bool _isRamModalOpen;
  191. private void EditRam()
  192. {
  193. _isRamModalOpen = true;
  194. }
  195. private async Task HandleRamSubmit(Ram value)
  196. {
  197. _isRamModalOpen = false;
  198. await UpdateLaptopUseCase.ExecuteAsync(Laptop.Name, Laptop.Model, value.Size, value.Mts);
  199. Laptop = await GetLaptopUseCase.ExecuteAsync(Laptop.Name);
  200. }
  201. #endregion
  202. #region CPU
  203. bool _cpuModalOpen;
  204. int _editingCpuIndex;
  205. Cpu? _editingCpu;
  206. void OpenAddCpu()
  207. {
  208. _editingCpuIndex = -1;
  209. _editingCpu = null;
  210. _cpuModalOpen = true;
  211. }
  212. void OpenEditCpu(Cpu cpu)
  213. {
  214. _editingCpu = cpu;
  215. Laptop.Cpus ??= new List<Cpu>();
  216. _editingCpuIndex = Laptop.Cpus.IndexOf(cpu);
  217. ;
  218. _cpuModalOpen = true;
  219. }
  220. async Task HandleCpuSubmit(Cpu cpu)
  221. {
  222. Laptop.Cpus ??= new List<Cpu>();
  223. if (_editingCpuIndex < 0)
  224. {
  225. await AddCpuUseCase.ExecuteAsync(Laptop.Name, cpu.Model, cpu.Cores, cpu.Threads);
  226. }
  227. else
  228. {
  229. await UpdateCpuUseCase.ExecuteAsync(Laptop.Name, _editingCpuIndex, cpu.Model, cpu.Cores, cpu.Threads);
  230. }
  231. Laptop = await GetLaptopUseCase.ExecuteAsync(Laptop.Name);
  232. }
  233. async Task HandleCpuDelete(Cpu cpu)
  234. {
  235. await RemoveCpuUseCase.ExecuteAsync(Laptop.Name, _editingCpuIndex);
  236. Laptop = await GetLaptopUseCase.ExecuteAsync(Laptop.Name);
  237. }
  238. #endregion
  239. #region Drives
  240. bool _driveModalOpen;
  241. int _editingDriveIndex;
  242. Drive? _editingDrive;
  243. void OpenAddDrive()
  244. {
  245. _editingDriveIndex = -1;
  246. _editingDrive = null;
  247. _driveModalOpen = true;
  248. }
  249. void OpenEditDrive(Drive drive)
  250. {
  251. _editingDrive = drive;
  252. Laptop.Drives ??= new List<Drive>();
  253. _editingDriveIndex = Laptop.Drives.IndexOf(drive);
  254. ;
  255. _driveModalOpen = true;
  256. }
  257. async Task HandleDriveSubmit(Drive drive)
  258. {
  259. Laptop.Drives ??= new List<Drive>();
  260. if (_editingDriveIndex < 0)
  261. {
  262. await AddDriveUseCase.ExecuteAsync(Laptop.Name, drive.Type, drive.Size);
  263. }
  264. else
  265. {
  266. await UpdateDriveUseCase.ExecuteAsync(Laptop.Name, _editingDriveIndex, drive.Type, drive.Size);
  267. }
  268. Laptop = await GetLaptopUseCase.ExecuteAsync(Laptop.Name);
  269. StateHasChanged();
  270. }
  271. async Task HandleDriveDelete(Drive drive)
  272. {
  273. await RemoveDriveUseCase.ExecuteAsync(Laptop.Name, _editingDriveIndex);
  274. Laptop = await GetLaptopUseCase.ExecuteAsync(Laptop.Name);
  275. StateHasChanged();
  276. }
  277. #endregion
  278. #region GPUs
  279. bool _gpuModalOpen;
  280. int _editingGpuIndex;
  281. Gpu? _editingGpu;
  282. void OpenAddGpu()
  283. {
  284. _editingGpuIndex = -1;
  285. _editingGpu = null;
  286. _gpuModalOpen = true;
  287. }
  288. void OpenEditGpu(Gpu gpu)
  289. {
  290. Laptop.Gpus ??= new List<Gpu>();
  291. _editingGpuIndex = Laptop.Gpus.IndexOf(gpu);
  292. _editingGpu = gpu;
  293. _gpuModalOpen = true;
  294. }
  295. async Task HandleGpuSubmit(Gpu gpu)
  296. {
  297. Laptop.Gpus ??= new List<Gpu>();
  298. if (_editingGpuIndex < 0)
  299. {
  300. await AddGpuUseCase.ExecuteAsync(
  301. Laptop.Name,
  302. gpu.Model,
  303. gpu.Vram);
  304. }
  305. else
  306. {
  307. await UpdateGpuUseCase.ExecuteAsync(
  308. Laptop.Name,
  309. _editingGpuIndex,
  310. gpu.Model,
  311. gpu.Vram);
  312. }
  313. Laptop = await GetLaptopUseCase.ExecuteAsync(Laptop.Name);
  314. }
  315. async Task HandleGpuDelete(Gpu gpu)
  316. {
  317. await RemoveGpuUseCase.ExecuteAsync(Laptop.Name, _editingGpuIndex);
  318. Laptop = await GetLaptopUseCase.ExecuteAsync(Laptop.Name);
  319. }
  320. #endregion
  321. }
  322. @code {
  323. private bool _confirmDeleteOpen;
  324. [Parameter] public EventCallback<string> OnDeleted { get; set; }
  325. void ConfirmDelete()
  326. {
  327. _confirmDeleteOpen = true;
  328. }
  329. async Task DeleteServer()
  330. {
  331. _confirmDeleteOpen = false;
  332. await DeleteLaptopUseCase.ExecuteAsync(Laptop.Name);
  333. if (OnDeleted.HasDelegate)
  334. await OnDeleted.InvokeAsync(Laptop.Name);
  335. }
  336. }