CampaignMenu.qml 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. import QtQuick 2.15
  2. import QtQuick.Controls 2.15
  3. import QtQuick.Layouts 1.15
  4. import StandardOfIron 1.0
  5. Item {
  6. id: root
  7. property var campaigns: (typeof game !== "undefined" && game.available_campaigns) ? game.available_campaigns : []
  8. signal missionSelected(string campaignId)
  9. signal cancelled()
  10. anchors.fill: parent
  11. focus: true
  12. Keys.onPressed: function(event) {
  13. if (event.key === Qt.Key_Escape) {
  14. root.cancelled();
  15. event.accepted = true;
  16. }
  17. }
  18. Rectangle {
  19. anchors.fill: parent
  20. color: Theme.dim
  21. }
  22. Rectangle {
  23. id: container
  24. width: Math.min(parent.width * 0.85, 1200)
  25. height: Math.min(parent.height * 0.85, 800)
  26. anchors.centerIn: parent
  27. radius: Theme.radiusPanel
  28. color: Theme.panelBase
  29. border.color: Theme.panelBr
  30. border.width: 1
  31. opacity: 0.98
  32. ColumnLayout {
  33. anchors.fill: parent
  34. anchors.margins: Theme.spacingXLarge
  35. spacing: Theme.spacingLarge
  36. RowLayout {
  37. Layout.fillWidth: true
  38. spacing: Theme.spacingMedium
  39. Label {
  40. text: qsTr("Campaign Missions")
  41. color: Theme.textMain
  42. font.pointSize: Theme.fontSizeHero
  43. font.bold: true
  44. Layout.fillWidth: true
  45. }
  46. StyledButton {
  47. text: qsTr("← Back")
  48. onClicked: root.cancelled()
  49. }
  50. }
  51. Rectangle {
  52. Layout.fillWidth: true
  53. Layout.preferredHeight: 1
  54. color: Theme.border
  55. }
  56. ScrollView {
  57. Layout.fillWidth: true
  58. Layout.fillHeight: true
  59. clip: true
  60. ListView {
  61. id: listView
  62. model: root.campaigns
  63. spacing: Theme.spacingMedium
  64. delegate: Rectangle {
  65. width: listView.width
  66. height: 120
  67. radius: Theme.radiusLarge
  68. color: mouseArea.containsMouse ? Theme.hoverBg : Theme.cardBase
  69. border.color: mouseArea.containsMouse ? Theme.selectedBr : Theme.cardBorder
  70. border.width: 1
  71. MouseArea {
  72. id: mouseArea
  73. anchors.fill: parent
  74. hoverEnabled: true
  75. cursorShape: Qt.PointingHandCursor
  76. onClicked: {
  77. missionDetailPanel.visible = true;
  78. missionDetailPanel.campaignData = modelData;
  79. }
  80. }
  81. RowLayout {
  82. anchors.fill: parent
  83. anchors.margins: Theme.spacingMedium
  84. spacing: Theme.spacingMedium
  85. ColumnLayout {
  86. Layout.fillWidth: true
  87. spacing: Theme.spacingSmall
  88. RowLayout {
  89. Layout.fillWidth: true
  90. spacing: Theme.spacingSmall
  91. Label {
  92. text: modelData.title || ""
  93. color: Theme.textMain
  94. font.pointSize: Theme.fontSizeTitle
  95. font.bold: true
  96. Layout.fillWidth: true
  97. }
  98. Rectangle {
  99. visible: modelData.completed || false
  100. Layout.preferredWidth: 100
  101. Layout.preferredHeight: 24
  102. radius: Theme.radiusSmall
  103. color: Theme.successBg
  104. border.color: Theme.successBr
  105. border.width: 1
  106. Label {
  107. anchors.centerIn: parent
  108. text: qsTr("✓ Completed")
  109. color: Theme.successText
  110. font.pointSize: Theme.fontSizeSmall
  111. font.bold: true
  112. }
  113. }
  114. Rectangle {
  115. visible: !(modelData.unlocked || false)
  116. Layout.preferredWidth: 80
  117. Layout.preferredHeight: 24
  118. radius: Theme.radiusSmall
  119. color: Theme.disabledBg
  120. border.color: Theme.border
  121. border.width: 1
  122. Label {
  123. anchors.centerIn: parent
  124. text: qsTr("🔒 Locked")
  125. color: Theme.textDim
  126. font.pointSize: Theme.fontSizeSmall
  127. }
  128. }
  129. }
  130. Label {
  131. text: modelData.description || ""
  132. color: Theme.textSubLite
  133. wrapMode: Text.WordWrap
  134. maximumLineCount: 2
  135. elide: Text.ElideRight
  136. Layout.fillWidth: true
  137. font.pointSize: Theme.fontSizeMedium
  138. }
  139. }
  140. Text {
  141. text: "›"
  142. font.pointSize: Theme.fontSizeHero
  143. color: Theme.textHint
  144. }
  145. }
  146. Behavior on color {
  147. ColorAnimation {
  148. duration: Theme.animNormal
  149. }
  150. }
  151. Behavior on border.color {
  152. ColorAnimation {
  153. duration: Theme.animNormal
  154. }
  155. }
  156. }
  157. }
  158. }
  159. Label {
  160. visible: root.campaigns.length === 0
  161. text: qsTr("No campaign missions available")
  162. color: Theme.textDim
  163. font.pointSize: Theme.fontSizeMedium
  164. horizontalAlignment: Text.AlignHCenter
  165. Layout.fillWidth: true
  166. Layout.fillHeight: true
  167. }
  168. }
  169. }
  170. Rectangle {
  171. id: missionDetailPanel
  172. property var campaignData: null
  173. visible: false
  174. anchors.fill: parent
  175. color: Theme.dim
  176. z: 100
  177. MouseArea {
  178. anchors.fill: parent
  179. onClicked: missionDetailPanel.visible = false
  180. }
  181. Rectangle {
  182. width: Math.min(parent.width * 0.7, 900)
  183. height: Math.min(parent.height * 0.8, 700)
  184. anchors.centerIn: parent
  185. radius: Theme.radiusPanel
  186. color: Theme.panelBase
  187. border.color: Theme.panelBr
  188. border.width: 2
  189. MouseArea {
  190. anchors.fill: parent
  191. onClicked: {
  192. }
  193. }
  194. ColumnLayout {
  195. anchors.fill: parent
  196. anchors.margins: Theme.spacingXLarge
  197. spacing: Theme.spacingLarge
  198. Label {
  199. text: missionDetailPanel.campaignData ? (missionDetailPanel.campaignData.title || "") : ""
  200. color: Theme.textMain
  201. font.pointSize: Theme.fontSizeHero
  202. font.bold: true
  203. Layout.fillWidth: true
  204. }
  205. Label {
  206. text: missionDetailPanel.campaignData ? (missionDetailPanel.campaignData.description || "") : ""
  207. color: Theme.textSubLite
  208. wrapMode: Text.WordWrap
  209. Layout.fillWidth: true
  210. font.pointSize: Theme.fontSizeMedium
  211. }
  212. Rectangle {
  213. Layout.fillWidth: true
  214. Layout.fillHeight: true
  215. color: "#000000"
  216. border.color: Theme.border
  217. border.width: 1
  218. radius: Theme.radiusMedium
  219. Label {
  220. anchors.centerIn: parent
  221. text: qsTr("Mission Preview\n(Coming Soon)")
  222. color: Theme.textDim
  223. font.pointSize: Theme.fontSizeLarge
  224. horizontalAlignment: Text.AlignHCenter
  225. }
  226. }
  227. RowLayout {
  228. Layout.fillWidth: true
  229. spacing: Theme.spacingMedium
  230. Item {
  231. Layout.fillWidth: true
  232. }
  233. StyledButton {
  234. text: qsTr("Cancel")
  235. onClicked: missionDetailPanel.visible = false
  236. }
  237. StyledButton {
  238. text: qsTr("Start Mission")
  239. enabled: missionDetailPanel.campaignData ? (missionDetailPanel.campaignData.unlocked || false) : false
  240. onClicked: {
  241. if (missionDetailPanel.campaignData)
  242. root.missionSelected(missionDetailPanel.campaignData.id);
  243. }
  244. }
  245. }
  246. }
  247. }
  248. }
  249. }