@xcpcio/board-app 0.6.4 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/.eslintrc.json +6 -0
  2. package/LICENSE +1 -1
  3. package/README.md +13 -30
  4. package/cypress.config.ts +14 -0
  5. package/dist/_headers +3 -0
  6. package/dist/about.html +11 -0
  7. package/dist/assets/_...all_-27c7ae93.css +1 -0
  8. package/dist/assets/_...all_-d56798b5.js +3 -0
  9. package/dist/assets/_name_-8eab6137.js +1 -0
  10. package/dist/assets/about-a8cb8700.js +11 -0
  11. package/dist/assets/app-37f77a84.js +65 -0
  12. package/dist/assets/board-layout-deaedfc1.js +1 -0
  13. package/dist/assets/en-caedd340.js +1 -0
  14. package/dist/assets/home-49c336e5.js +1 -0
  15. package/dist/assets/index-a270cacd.css +5 -0
  16. package/dist/assets/index-layout-d65c80ea.js +1 -0
  17. package/dist/assets/test-0a3d6f7a.js +1 -0
  18. package/dist/assets/user-108782a1.js +1 -0
  19. package/dist/assets/virtual_pwa-register-1c1b9161.js +1 -0
  20. package/dist/assets/workbox-window.prod.es5-a7b12eab.js +2 -0
  21. package/dist/assets/zh-CN-86269804.js +1 -0
  22. package/dist/favicon-dark.svg +1 -0
  23. package/dist/favicon.svg +1 -0
  24. package/dist/index.html +1 -171
  25. package/dist/manifest.webmanifest +1 -0
  26. package/dist/pwa-192x192.png +0 -0
  27. package/dist/pwa-512x512.png +0 -0
  28. package/dist/robots.txt +4 -0
  29. package/dist/safari-pinned-tab.svg +41 -0
  30. package/dist/sitemap.xml +1 -0
  31. package/dist/ssr-manifest.json +486 -0
  32. package/dist/sw.js +1 -0
  33. package/dist/test.html +1 -0
  34. package/dist/workbox-b8d87ee1.js +1 -0
  35. package/package.json +94 -50
  36. package/public/_headers +3 -0
  37. package/public/favicon-dark.svg +1 -0
  38. package/public/favicon.svg +1 -0
  39. package/public/pwa-192x192.png +0 -0
  40. package/public/pwa-512x512.png +0 -0
  41. package/public/safari-pinned-tab.svg +41 -0
  42. package/src/App.vue +33 -0
  43. package/src/auto-imports.d.ts +909 -0
  44. package/src/components/ContestIndex.vue +227 -0
  45. package/src/components/Footer.vue +94 -0
  46. package/src/components/GoBack.vue +22 -0
  47. package/src/components/NavBar.vue +152 -0
  48. package/src/components/SearchInput.vue +50 -0
  49. package/src/components/TheCounter.vue +19 -0
  50. package/src/components/TheInput.vue +20 -0
  51. package/src/components/board/Balloon.vue +5 -0
  52. package/src/components/board/Board.vue +396 -0
  53. package/src/components/board/BottomStatistics.vue +159 -0
  54. package/src/components/board/ContestStateBadge.vue +41 -0
  55. package/src/components/board/Export.vue +75 -0
  56. package/src/components/board/Modal.vue +107 -0
  57. package/src/components/board/ModalMenu.vue +64 -0
  58. package/src/components/board/OptionsModal.vue +179 -0
  59. package/src/components/board/Progress.less +442 -0
  60. package/src/components/board/Progress.vue +229 -0
  61. package/src/components/board/SecondLevelMenu.vue +190 -0
  62. package/src/components/board/Standings.less +1162 -0
  63. package/src/components/board/Standings.vue +154 -0
  64. package/src/components/board/StandingsAnnotate.vue +38 -0
  65. package/src/components/board/Statistics.vue +77 -0
  66. package/src/components/board/SubmissionsTable.vue +312 -0
  67. package/src/components/board/SubmissionsTableModal.vue +52 -0
  68. package/src/components/board/TeamAwards.vue +93 -0
  69. package/src/components/board/TeamInfoModal.vue +128 -0
  70. package/src/components/board/TeamProblemBlock.vue +100 -0
  71. package/src/components/board/TeamUI.vue +161 -0
  72. package/src/components/board/Utility.vue +28 -0
  73. package/src/components/icon/GirlIcon.vue +80 -0
  74. package/src/components/icon/RightArrowIcon.vue +26 -0
  75. package/src/components/icon/StarIcon.vue +19 -0
  76. package/src/components/table/TablePagination.vue +108 -0
  77. package/src/components.d.ts +44 -0
  78. package/src/composables/dark.ts +4 -0
  79. package/src/composables/pagination.ts +81 -0
  80. package/src/composables/statistics.ts +280 -0
  81. package/src/composables/useLocalStorage.ts +29 -0
  82. package/src/composables/useQueryBoardData.ts +43 -0
  83. package/src/composables/utils.ts +11 -0
  84. package/src/layouts/board-layout.vue +14 -0
  85. package/src/layouts/default.vue +10 -0
  86. package/src/layouts/home.vue +12 -0
  87. package/src/layouts/index-layout.vue +15 -0
  88. package/src/main.ts +36 -0
  89. package/src/modules/README.md +11 -0
  90. package/src/modules/i18n.ts +52 -0
  91. package/src/modules/nprogress.ts +15 -0
  92. package/src/modules/pinia.ts +18 -0
  93. package/src/modules/pwa.ts +15 -0
  94. package/src/modules/toast.ts +10 -0
  95. package/src/pages/[...all].vue +34 -0
  96. package/src/pages/about.md +21 -0
  97. package/src/pages/hi/[name].vue +50 -0
  98. package/src/pages/index.vue +129 -0
  99. package/src/pages/test.vue +57 -0
  100. package/src/shims.d.ts +16 -0
  101. package/src/stores/user.ts +36 -0
  102. package/src/styles/color.css +51 -0
  103. package/src/styles/main.css +30 -0
  104. package/src/styles/markdown.css +28 -0
  105. package/src/styles/submission-status.css +123 -0
  106. package/src/types.ts +3 -0
  107. package/tsconfig.json +39 -0
  108. package/uno.config.ts +65 -0
  109. package/vite.config.ts +176 -0
  110. package/dist/favicon.ico +0 -0
  111. package/dist/umi.00ae29f6.js +0 -1
  112. package/dist/umi.bd64c248.css +0 -1
@@ -0,0 +1,154 @@
1
+ <script setup lang="ts">
2
+ import type { Rank } from "@xcpcio/core";
3
+
4
+ const props = defineProps<{
5
+ rank: Rank,
6
+ }>();
7
+
8
+ const { t } = useI18n();
9
+
10
+ const rank = computed(() => props.rank);
11
+ const teams = computed(() => props.rank.teams);
12
+
13
+ const filterTeams = computed(() => {
14
+ const res = props.rank.teams.filter((t) => {
15
+ if (props.rank.organizations) {
16
+ if (props.rank.options.filterOrganizationMap.has(t.organization)) {
17
+ return true;
18
+ }
19
+ }
20
+
21
+ if (props.rank.options.filterTeamMap.has(t.id)) {
22
+ return true;
23
+ }
24
+
25
+ return false;
26
+ });
27
+
28
+ return res;
29
+ });
30
+
31
+ const maxOrgLength = computed(() => {
32
+ let res = 0;
33
+ rank.value.teams.forEach((t) => {
34
+ res = Math.max(res, t.organization.length);
35
+ });
36
+
37
+ return res;
38
+ });
39
+
40
+ const maxTeamLength = computed(() => {
41
+ let res = 0;
42
+ rank.value.teams.forEach((t) => {
43
+ res = Math.max(res, t.name.length);
44
+ });
45
+
46
+ return res;
47
+ });
48
+ </script>
49
+
50
+ <template>
51
+ <div>
52
+ <div>
53
+ <table
54
+ class="standings"
55
+ font-mono dark:text-gray-700
56
+ >
57
+ <thead
58
+ class="sticky top-0 z-99"
59
+ >
60
+ <tr>
61
+ <th
62
+ class="title"
63
+ style="width: 3rem;"
64
+ >
65
+ {{ t("standings.place") }}
66
+ </th>
67
+ <th
68
+ v-if="rank.contest.badge"
69
+ class="title"
70
+ style="width: 2rem;"
71
+ >
72
+ {{ rank.contest.badge }}
73
+ </th>
74
+ <th
75
+ v-if="rank.contest.organization"
76
+ class="title"
77
+ :style="{ width: `${Math.min(32, Math.ceil(maxOrgLength * 1.1))}rem` }"
78
+ >
79
+ {{ rank.contest.organization }}
80
+ </th>
81
+ <th
82
+ class="title"
83
+ :style="{ width: `${Math.min(32, Math.ceil(maxTeamLength * 1))}rem` }"
84
+ >
85
+ {{ t("standings.team") }}
86
+ </th>
87
+ <th
88
+ class="title"
89
+ style="width: 3rem;"
90
+ >
91
+ {{ t("standings.solved") }}
92
+ </th>
93
+ <th
94
+ class="title"
95
+ style="width: 4rem;"
96
+ >
97
+ {{ t("standings.penalty") }}
98
+ </th>
99
+ <th
100
+ v-for="p in rank.contest.problems"
101
+ :key="p.id"
102
+ class="success"
103
+ text-center
104
+ style="width: 3rem;"
105
+ :style="{
106
+ 'background-color': p.balloonColor?.background_color,
107
+ 'color': p.balloonColor?.color,
108
+ }"
109
+ >
110
+ {{ p.label }}
111
+ <br>
112
+ <s>{{ p.statistics.acceptedNum }}</s>
113
+ </th>
114
+ <th class="title" style="width: 2.5rem;">
115
+ {{ t("standings.dict") }}
116
+ </th>
117
+ </tr>
118
+ </thead>
119
+ <tbody>
120
+ <template
121
+ v-for="(team, ix) in filterTeams"
122
+ :key="`filter-${team.id}`"
123
+ >
124
+ <TeamUI
125
+ :ix="ix"
126
+ :rank="rank"
127
+ :team="team"
128
+ :is-filter="true"
129
+ />
130
+ </template>
131
+
132
+ <template
133
+ v-for="(team, ix) in teams"
134
+ :key="team.id"
135
+ >
136
+ <TeamUI
137
+ :ix="ix"
138
+ :rank="rank"
139
+ :team="team"
140
+ />
141
+ </template>
142
+
143
+ <BottomStatistics
144
+ :rank="rank"
145
+ />
146
+ </tbody>
147
+ </table>
148
+ </div>
149
+ </div>
150
+ </template>
151
+
152
+ <style scoped lang="less">
153
+ @import "./Standings.less";
154
+ </style>
@@ -0,0 +1,38 @@
1
+ <template>
2
+ <div class="flex items-center justify-center dark:text-black">
3
+ <table>
4
+ <tbody>
5
+ <tr>
6
+ <td class="gold">
7
+ Gold
8
+ </td>
9
+ <td class="silver">
10
+ Silver
11
+ </td>
12
+ <td class="bronze">
13
+ Bronze
14
+ </td>
15
+ <td class="honorable">
16
+ Honorable
17
+ </td>
18
+ <td class="first-solve">
19
+ First to solve problem
20
+ </td>
21
+ <td class="correct">
22
+ Solved problem
23
+ </td>
24
+ <td class="incorrect">
25
+ Attempted problem
26
+ </td>
27
+ <td class="pending">
28
+ Pending judgement
29
+ </td>
30
+ </tr>
31
+ </tbody>
32
+ </table>
33
+ </div>
34
+ </template>
35
+
36
+ <style scoped lang="less">
37
+ @import "./Standings.less";
38
+ </style>
@@ -0,0 +1,77 @@
1
+ <script setup lang="ts">
2
+ import { Chart } from "highcharts-vue";
3
+
4
+ import type { Rank } from "@xcpcio/core";
5
+
6
+ const props = defineProps<{
7
+ rank: Rank,
8
+ }>();
9
+
10
+ const { t } = useI18n();
11
+
12
+ const rank = computed(() => props.rank);
13
+
14
+ function getHeadData() {
15
+ const l = [];
16
+
17
+ l.push({
18
+ title: "standings.statistics.head_data.problems",
19
+ data: rank.value.contest.problems.length,
20
+ });
21
+
22
+ l.push({
23
+ title: "standings.statistics.head_data.teams",
24
+ data: rank.value.teams.length,
25
+ });
26
+
27
+ l.push({
28
+ title: "standings.statistics.head_data.submissions",
29
+ data: rank.value.getSubmissions().length,
30
+ });
31
+
32
+ return l;
33
+ }
34
+ </script>
35
+
36
+ <template>
37
+ <div
38
+ class="w-88vw flex flex-col md:w-92vw"
39
+ >
40
+ <section>
41
+ <div class="mx-auto max-w-screen-xl px-4 py-4 lg:px-6 lg:py-6">
42
+ <div class="lg:grid lg:grid-cols-3 sm:gap-6 xl:gap-10 space-y-8 lg:space-y-0">
43
+ <div v-for="h in getHeadData()" :key="h.title">
44
+ <div class="mx-auto max-w-[16rem] flex flex-col border border-gray-100 rounded-lg bg-white p-6 text-center text-gray-900 shadow dark:border-gray-600 dark:bg-gray-800 xl:p-8 dark:text-white">
45
+ <h3 class="mb-4 text-2xl font-semibold">
46
+ {{ t(h.title) }}
47
+ </h3>
48
+ <div class="my-8 flex items-baseline justify-center">
49
+ <span class="mr-2 text-5xl font-extrabold">{{ h.data }}</span>
50
+ </div>
51
+ </div>
52
+ </div>
53
+ </div>
54
+ </div>
55
+ </section>
56
+
57
+ <div class="mt-8 flex flex-col gap-8">
58
+ <div>
59
+ <Chart
60
+ :options="getSubmitChart(rank)"
61
+ />
62
+ </div>
63
+
64
+ <div>
65
+ <Chart
66
+ :options="getProblemChart(rank)"
67
+ />
68
+ </div>
69
+
70
+ <div>
71
+ <Chart
72
+ :options="getTeamChart(rank)"
73
+ />
74
+ </div>
75
+ </div>
76
+ </div>
77
+ </template>
@@ -0,0 +1,312 @@
1
+ <script setup lang="ts">
2
+ import type { Rank, Submissions } from "@xcpcio/core";
3
+ import { Submission } from "@xcpcio/core";
4
+ import { SubmissionStatusToString } from "@xcpcio/types";
5
+
6
+ import { Pagination } from "~/composables/pagination";
7
+
8
+ const props = defineProps<{
9
+ rank: Rank,
10
+ submissions: Submissions,
11
+ pageSize?: number,
12
+ removeBorder?: boolean,
13
+ }>();
14
+
15
+ const rank = computed(() => props.rank);
16
+ const submissions = computed(() => {
17
+ const s = props.submissions;
18
+ return s.sort(Submission.compare).reverse();
19
+ });
20
+
21
+ const p = ref(new Pagination());
22
+
23
+ p.value.currentPage = 0;
24
+ p.value.pageSize = props.pageSize ?? 16;
25
+ p.value.totalSize = submissions.value.length;
26
+
27
+ watch(submissions, () => {
28
+ p.value.totalSize = submissions.value.length;
29
+
30
+ if (p.value.currentPage >= p.value.totalPage) {
31
+ p.value.currentPage = p.value.totalPage - 1;
32
+ }
33
+ });
34
+
35
+ const currentSubmissions = computed(() => {
36
+ return submissions.value.slice(p.value.currentLeft, p.value.currentRight);
37
+ });
38
+
39
+ const notShowing = ref(false);
40
+
41
+ function getSubmitTime(
42
+ timeDiff: number,
43
+ ): string {
44
+ const h = Math.floor(timeDiff / 3600);
45
+ const m = Math.floor(timeDiff % 3600 / 60);
46
+ const s = timeDiff % 60;
47
+
48
+ const f = (x: number) => x.toString().padStart(2, "0");
49
+
50
+ return `${f(h)}:${f(m)}:${f(s)}`;
51
+ }
52
+
53
+ function getProblemLabelColorClass(s: Submission) {
54
+ const defaultClass = "bg-primary-100 text-primary-800 dark:bg-primary-900 dark:text-primary-300";
55
+
56
+ const pId = s.problemId;
57
+ const p = rank.value.contest.problemsMap.get(pId);
58
+
59
+ if (p === null || p === undefined || !p.balloonColor) {
60
+ return defaultClass;
61
+ }
62
+ }
63
+
64
+ function getProblemLabelColorStyle(s: Submission) {
65
+ const pId = s.problemId;
66
+ const p = rank.value.contest.problemsMap.get(pId);
67
+
68
+ if (p === null || p === undefined || !p.balloonColor) {
69
+ return undefined;
70
+ }
71
+
72
+ const b = p.balloonColor;
73
+
74
+ return {
75
+ backgroundColor: b.background_color as string,
76
+ color: b.color as string,
77
+ };
78
+ }
79
+ </script>
80
+
81
+ <template>
82
+ <section>
83
+ <div
84
+ class="mx-auto w-full"
85
+ px-4
86
+ >
87
+ <div
88
+ class="relative overflow-hidden bg-white dark:bg-gray-800"
89
+ :class="{
90
+ 'shadow-md': props.removeBorder !== true,
91
+ 'sm:rounded-sm': props.removeBorder !== true,
92
+ }"
93
+ >
94
+ <div
95
+ class="lg:flex-row lg:items-center lg:justify-between space-y-3 lg:space-x-4 lg:space-y-0"
96
+ flex flex-col
97
+ px-4 py-3
98
+ >
99
+ <div
100
+ class="flex flex-shrink-0 flex-col md:flex-row md:items-center lg:justify-end space-y-3 md:space-x-3 md:space-y-0"
101
+ >
102
+ <button
103
+ v-if="notShowing"
104
+ type="button"
105
+ class="flex items-center justify-center rounded-lg bg-primary-700 px-4 py-2 text-sm font-medium text-white dark:bg-primary-600 hover:bg-primary-800 focus:outline-none focus:ring-4 focus:ring-primary-300 dark:hover:bg-primary-700 dark:focus:ring-primary-800"
106
+ >
107
+ <svg
108
+ class="mr-2 h-3.5 w-3.5"
109
+ fill="currentColor"
110
+ viewbox="0 0 20 20"
111
+ xmlns="http://www.w3.org/2000/svg"
112
+ aria-hidden="true"
113
+ >
114
+ <path
115
+ clip-rule="evenodd"
116
+ fill-rule="evenodd"
117
+ d="M10 3a1 1 0 011 1v5h5a1 1 0 110 2h-5v5a1 1 0 11-2 0v-5H4a1 1 0 110-2h5V4a1 1 0 011-1z"
118
+ />
119
+ </svg>
120
+ Add new product
121
+ </button>
122
+
123
+ <button
124
+ v-if="notShowing"
125
+ type="button"
126
+ class="flex flex-shrink-0 items-center justify-center border border-gray-200 rounded-lg bg-white px-3 py-2 text-sm font-medium text-gray-900 focus:z-10 dark:border-gray-600 dark:bg-gray-800 hover:bg-gray-100 dark:text-gray-400 hover:text-primary-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:hover:bg-gray-700 dark:hover:text-white dark:focus:ring-gray-700"
127
+ >
128
+ <svg
129
+ class="mr-2 h-4 w-4"
130
+ xmlns="http://www.w3.org/2000/svg"
131
+ aria-hidden="true"
132
+ fill="none"
133
+ viewbox="0 0 24 24"
134
+ stroke-width="1.5"
135
+ stroke="currentColor"
136
+ >
137
+ <path
138
+ stroke-linecap="round"
139
+ stroke-linejoin="round"
140
+ d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0l3.181 3.183a8.25 8.25 0 0013.803-3.7M4.031 9.865a8.25 8.25 0 0113.803-3.7l3.181 3.182m0-4.991v4.99"
141
+ />
142
+ </svg>
143
+ Update stocks 1/250
144
+ </button>
145
+
146
+ <button
147
+ v-if="notShowing"
148
+ type="button"
149
+ class="flex flex-shrink-0 items-center justify-center border border-gray-200 rounded-lg bg-white px-3 py-2 text-sm font-medium text-gray-900 focus:z-10 dark:border-gray-600 dark:bg-gray-800 hover:bg-gray-100 dark:text-gray-400 hover:text-primary-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:hover:bg-gray-700 dark:hover:text-white dark:focus:ring-gray-700"
150
+ >
151
+ <div
152
+ i-pajamas-export
153
+ class="mr-2 h-4 w-4"
154
+ />
155
+ Export
156
+ </button>
157
+ </div>
158
+ </div>
159
+
160
+ <div
161
+ class="overflow-x-auto"
162
+ >
163
+ <table
164
+ class="w-full text-left text-sm text-gray-500 dark:text-gray-400"
165
+ font-medium font-mono
166
+ >
167
+ <thead class="bg-gray-50 text-xs uppercase text-gray-700 dark:bg-gray-700 dark:text-gray-400">
168
+ <tr>
169
+ <th
170
+ scope="col"
171
+ class="px-4 py-3"
172
+ >
173
+ Problem
174
+ </th>
175
+ <th
176
+ v-if="rank.contest.organization"
177
+ scope="col"
178
+ class="px-4 py-3"
179
+ >
180
+ {{ rank.contest.organization }}
181
+ </th>
182
+ <th
183
+ scope="col"
184
+ class="px-4 py-3"
185
+ >
186
+ Team
187
+ </th>
188
+ <th
189
+ scope="col"
190
+ class="px-4 py-3"
191
+ >
192
+ Status
193
+ </th>
194
+ <th
195
+ v-if="notShowing"
196
+ scope="col"
197
+ class="px-4 py-3"
198
+ >
199
+ Time
200
+ </th>
201
+ <th
202
+ v-if="notShowing"
203
+ scope="col"
204
+ class="px-4 py-3"
205
+ >
206
+ Memory
207
+ </th>
208
+ <th
209
+ v-if="notShowing"
210
+ scope="col"
211
+ class="px-4 py-3"
212
+ >
213
+ Answer
214
+ </th>
215
+ <th
216
+ scope="col"
217
+ class="px-4 py-3"
218
+ >
219
+ Submit Time
220
+ </th>
221
+ </tr>
222
+ </thead>
223
+
224
+ <tbody>
225
+ <template
226
+ v-for="s in currentSubmissions"
227
+ :key="s.id"
228
+ >
229
+ <tr
230
+ class="border-b dark:border-gray-600 hover:bg-gray-100 dark:hover:bg-gray-700"
231
+ >
232
+ <td
233
+ px-4 py-2
234
+ >
235
+ <span
236
+ class="rounded px-2 py-0.5 text-sm"
237
+ :class="[getProblemLabelColorClass(s)]"
238
+ :style="getProblemLabelColorStyle(s)"
239
+ >
240
+ {{ rank.contest.problemsMap.get(s.problemId)?.label }}
241
+ </span>
242
+ </td>
243
+
244
+ <td
245
+ v-if="rank.contest.organization"
246
+ class="whitespace-nowrap px-4 py-2 text-gray-900 dark:text-white"
247
+ >
248
+ {{ rank.teamsMap.get(s.teamId)?.organization }}
249
+ </td>
250
+
251
+ <td class="whitespace-nowrap px-4 py-2 text-gray-900 dark:text-white">
252
+ {{ rank.teamsMap.get(s.teamId)?.name }}
253
+ </td>
254
+
255
+ <td
256
+ scope="row"
257
+ :class="[s.status.toString()]"
258
+ whitespace-nowrap px-4 py-2
259
+ flex items-center
260
+ font-bold
261
+ >
262
+ {{ SubmissionStatusToString[s.status] }}
263
+ </td>
264
+
265
+ <td
266
+ v-if="notShowing"
267
+ class="whitespace-nowrap px-4 py-2 text-gray-900 dark:text-white"
268
+ >
269
+ <div class="flex items-center">
270
+ <div class="mr-2 inline-block h-4 w-4 rounded-full bg-red-700" />
271
+ 95
272
+ </div>
273
+ </td>
274
+
275
+ <td
276
+ v-if="notShowing"
277
+ class="whitespace-nowrap px-4 py-2 text-gray-900 dark:text-white"
278
+ >
279
+ 0.47
280
+ </td>
281
+
282
+ <td
283
+ v-if="notShowing"
284
+ class="whitespace-nowrap px-4 py-2 text-gray-900 dark:text-white"
285
+ >
286
+ <div class="flex items-center">
287
+ <span class="ml-1 text-gray-500 dark:text-gray-400">5.0</span>
288
+ </div>
289
+ </td>
290
+
291
+ <td class="whitespace-nowrap px-4 py-2 text-gray-900 dark:text-white">
292
+ <div class="flex items-center">
293
+ {{ getSubmitTime(s.timestamp) }}
294
+ </div>
295
+ </td>
296
+ </tr>
297
+ </template>
298
+ </tbody>
299
+ </table>
300
+ </div>
301
+
302
+ <TablePagination
303
+ v-model:pagination="p"
304
+ />
305
+ </div>
306
+ </div>
307
+ </section>
308
+ </template>
309
+
310
+ <style scoped lang="less">
311
+ @import "../../styles/submission-status.css";
312
+ </style>
@@ -0,0 +1,52 @@
1
+ <script setup lang="ts">
2
+ import type { Rank, Team, TeamProblemStatistics } from "@xcpcio/core";
3
+
4
+ const props = defineProps<{
5
+ isHidden: boolean,
6
+
7
+ rank: Rank,
8
+ team: Team,
9
+ p: TeamProblemStatistics,
10
+ }>();
11
+
12
+ const emit = defineEmits(["update:isHidden"]);
13
+
14
+ const isHidden = computed({
15
+ get() {
16
+ return props.isHidden;
17
+ },
18
+ set(value) {
19
+ emit("update:isHidden", value);
20
+ },
21
+ });
22
+
23
+ const rank = computed(() => props.rank);
24
+ const team = computed(() => props.team);
25
+ const p = computed(() => props.p);
26
+
27
+ const headerTitle = computed(() => {
28
+ return `${team.value.name} - ${p.value.problem.label}`;
29
+ });
30
+ </script>
31
+
32
+ <template>
33
+ <Modal
34
+ v-model:isHidden="isHidden"
35
+ :title="headerTitle"
36
+ >
37
+ <div
38
+ w-full
39
+ font-bold font-mono
40
+ flex items-center justify-center
41
+ class="mt-[-12px]"
42
+ >
43
+ <SubmissionsTable
44
+ w-full
45
+ :rank="rank"
46
+ :submissions="p.submissions"
47
+ :page-size="8"
48
+ :remove-border="true"
49
+ />
50
+ </div>
51
+ </Modal>
52
+ </template>