Skip to content

Commit 8c4eae8

Browse files
authored
Merge pull request #1904 from AtCoder-NoviSteps/#1901
✨ Publish contest table (#1901)
2 parents ac06eb7 + 1ea33af commit 8c4eae8

File tree

9 files changed

+60
-46
lines changed

9 files changed

+60
-46
lines changed

src/lib/components/ExternalLinkWrapper.svelte

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
textColorInDarkMode?: string;
99
textOverflow?: string;
1010
iconSize?: number;
11+
useInlineFlex?: boolean;
1112
}
1213
1314
let {
@@ -17,12 +18,13 @@
1718
textColorInDarkMode = 'dark:text-primary-500',
1819
textOverflow = '',
1920
iconSize = 4,
21+
useInlineFlex = true,
2022
}: Props = $props();
2123
</script>
2224

2325
<a
2426
href={url}
25-
class={`inline-flex items-center font-medium ${textSize} text-primary-600 hover:underline ${textColorInDarkMode}`}
27+
class={`${useInlineFlex ? 'inline-flex' : ''} items-center font-medium ${textSize} text-primary-600 hover:underline ${textColorInDarkMode}`}
2628
target="_blank"
2729
rel="noreferrer"
2830
>

src/lib/components/GradeLabel.svelte

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,23 @@
2525
2626
let grade = $derived(getTaskGradeLabel(taskGrade));
2727
let gradeColor = $derived(getTaskGradeColor(taskGrade));
28+
29+
function addGradientIfNeeds(taskGrade: TaskGrade | string) {
30+
if (taskGrade === TaskGrade.D6) {
31+
const bronze =
32+
'bg-gradient-to-br from-atcoder-D6 via-stone-600 to-amber-600 shadow-inner shadow shadow-amber-900/80 ring-2 ring-amber-300/50 text-amber-50 font-bold drop-shadow relative overflow-hidden';
33+
return bronze;
34+
}
35+
return '';
36+
}
37+
38+
let gradient = $derived(addGradientIfNeeds(taskGrade));
2839
</script>
2940

30-
<div class="rounded-lg border-2 {toChangeBorderColorIfNeeds(grade)}">
41+
<div class="rounded-lg border-2 {toChangeBorderColorIfNeeds(grade)} {gradient ? 'shadow-md' : ''}">
3142
<div
32-
class="p-{defaultPadding} w-{reducedWidth} xs:w-{defaultWidth} text-sm xs:text-{defaultTextSize} text-center rounded-md {toChangeTextColorIfNeeds(
33-
grade,
34-
)} {gradeColor}"
43+
class="p-{defaultPadding} w-{reducedWidth} xs:w-{defaultWidth} text-sm xs:text-{defaultTextSize} text-center rounded-md
44+
{gradient || toChangeTextColorIfNeeds(grade) + ' ' + gradeColor}"
3545
>
3646
{#if taskGrade !== TaskGrade.PENDING}
3747
{grade}

src/lib/components/SubmissionStatus/AcceptedCounter.svelte

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,9 @@
2121
});
2222
</script>
2323

24-
<!-- FIXME: 横幅を微調整する -->
2524
<!-- See: -->
2625
<!-- https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed -->
27-
<div class="text-xs xs:text-sm w-max-[72px] w-max-[96px] text-center">
26+
<div class="text-xs md:text-sm w-min-[72px] w-max-[96px] text-center">
2827
<div>
2928
{acceptedCount} / {allTaskCount}
3029
</div>

src/lib/components/TaskList.svelte

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
3434
let { grade, taskResults, isAdmin, isLoggedIn }: Props = $props();
3535
36-
// TODO: 他のコンポーネントでも利用できるようにする。
3736
let updatingModal: UpdatingModal | null = null;
3837
3938
function openModal(taskResult: TaskResult): void {
@@ -48,17 +47,24 @@
4847
<Accordion flush>
4948
<AccordionItem>
5049
{#snippet header()}
51-
<span class="flex justify-around w-full place-items-center">
52-
<GradeLabel
53-
taskGrade={grade}
54-
defaultPadding={0.25}
55-
defaultWidth={12}
56-
reducedWidth={9}
57-
defaultTextSize="xl"
58-
/>
50+
<span class="grid grid-cols-[1fr_6fr_0fr] sm:grid-cols-[1fr_6fr_1fr] w-full items-center">
51+
<div class="flex justify-center">
52+
<GradeLabel
53+
taskGrade={grade}
54+
defaultPadding={0.25}
55+
defaultWidth={12}
56+
reducedWidth={9}
57+
defaultTextSize="xl"
58+
/>
59+
</div>
5960

60-
<ThermometerProgressBar {taskResults} />
61-
<AcceptedCounter {taskResults} />
61+
<div class="flex justify-center">
62+
<ThermometerProgressBar {taskResults} width="w-5/6 md:w-11/12 lg:w-full" />
63+
</div>
64+
65+
<div class="hidden sm:flex justify-center">
66+
<AcceptedCounter {taskResults} />
67+
</div>
6268
</span>
6369
{/snippet}
6470

src/lib/components/TaskTables/TaskTableBodyCell.svelte

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,14 @@
4343
{/snippet}
4444

4545
{#snippet taskTitleAndExternalLink(taskResult: TaskResult)}
46-
<div class="max-w-[calc(100%-2rem)] truncate">
46+
<div class="max-w-[calc(100%-1rem)] truncate">
4747
<ExternalLinkWrapper
4848
url={getTaskUrl(taskResult.contest_id, taskResult.task_id)}
4949
description={removeTaskIndexFromTitle(taskResult.title, taskResult.task_table_index)}
5050
textSize="xs:text-md"
5151
textColorInDarkMode="dark:text-gray-300"
5252
iconSize={0}
53+
useInlineFlex={false}
5354
/>
5455
</div>
5556
{/snippet}

src/lib/stores/active_problem_list_tab.svelte.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
export type ActiveProblemListTab = 'contestTable' | 'listByGrade' | 'gradeGuidelineTable';
22

33
export class ActiveProblemListTabStore {
4-
value = $state<ActiveProblemListTab>('listByGrade');
4+
value = $state<ActiveProblemListTab>('contestTable');
55

66
/**
77
* Creates an instance with the specified problem list tab.
88
*
99
* @param activeTab - The default problem list tab to initialize.
10-
* Defaults to 'listByGrade'.
10+
* Defaults to 'contestTable'.
1111
*/
12-
constructor(activeTab: ActiveProblemListTab = 'listByGrade') {
12+
constructor(activeTab: ActiveProblemListTab = 'contestTable') {
1313
this.value = activeTab;
1414
}
1515

@@ -42,10 +42,10 @@ export class ActiveProblemListTabStore {
4242

4343
/**
4444
* Resets the active tab to the default value.
45-
* Sets the internal value to 'listByGrade'.
45+
* Sets the internal value to 'contestTable'.
4646
*/
4747
reset(): void {
48-
this.value = 'listByGrade';
48+
this.value = 'contestTable';
4949
}
5050
}
5151

src/routes/problems/+page.svelte

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,7 @@
3838
<!-- https://flowbite-svelte.com/docs/components/tabs -->
3939
<Tabs tabStyle="underline" contentClass="bg-white dark:bg-gray-800 mt-0 p-0">
4040
<!-- Contest table -->
41-
<!-- WIP: UIのデザインが試行錯誤の段階であるため、管理者のみ閲覧可能 -->
42-
<!-- TODO: 一般公開するときに、デフォルトで開くタブにする -->
43-
{#if isAdmin}
44-
{@render problemListTab('テーブル', 'contestTable', contestTable)}
45-
{/if}
41+
{@render problemListTab('テーブル(アルファ版)', 'contestTable', contestTable)}
4642

4743
<!-- Grades -->
4844
{@render problemListTab('グレード', 'listByGrade', listByGrade)}

src/test/lib/stores/active_problem_list_tab.svelte.test.ts

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,25 +11,25 @@ describe('ActiveProblemListTabStore', () => {
1111

1212
describe('constructor', () => {
1313
test('expects to initialize with default value', () => {
14-
expect(store.get()).toBe('listByGrade');
14+
expect(store.get()).toBe('contestTable');
1515
});
1616

1717
test('expects to initialize with provided value', () => {
18-
const customStore = new ActiveProblemListTabStore('contestTable');
19-
expect(customStore.get()).toBe('contestTable');
18+
const customStore = new ActiveProblemListTabStore('listByGrade');
19+
expect(customStore.get()).toBe('listByGrade');
2020
});
2121
});
2222

2323
describe('get', () => {
2424
test('expects to return the current active tab', () => {
25-
expect(store.get()).toBe('listByGrade');
25+
expect(store.get()).toBe('contestTable');
2626
});
2727
});
2828

2929
describe('set', () => {
3030
test('expects to update the active tab value', () => {
31-
store.set('contestTable');
32-
expect(store.get()).toBe('contestTable');
31+
store.set('listByGrade');
32+
expect(store.get()).toBe('listByGrade');
3333

3434
store.set('gradeGuidelineTable');
3535
expect(store.get()).toBe('gradeGuidelineTable');
@@ -38,24 +38,24 @@ describe('ActiveProblemListTabStore', () => {
3838

3939
describe('isSame', () => {
4040
test('expects to return true when active tab matches the argument', () => {
41-
store.set('contestTable');
42-
expect(store.isSame('contestTable')).toBe(true);
41+
store.set('listByGrade');
42+
expect(store.isSame('listByGrade')).toBe(true);
4343
});
4444

4545
test('expects to return false when active tab does not match the argument', () => {
46-
store.set('contestTable');
47-
expect(store.isSame('listByGrade')).toBe(false);
46+
store.set('listByGrade');
47+
expect(store.isSame('contestTable')).toBe(false);
4848
expect(store.isSame('gradeGuidelineTable')).toBe(false);
4949
});
5050
});
5151

5252
describe('reset', () => {
5353
test('expects to reset the active tab to the default value', () => {
54-
store.set('contestTable');
55-
expect(store.get()).toBe('contestTable');
54+
store.set('listByGrade');
55+
expect(store.get()).toBe('listByGrade');
5656

5757
store.reset();
58-
expect(store.get()).toBe('listByGrade');
58+
expect(store.get()).toBe('contestTable');
5959
});
6060
});
6161
});

tailwind.config.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,13 @@ const config = {
3737
Q10: '#e3cad8',
3838
Q9: '#e4cde0',
3939
Q8: '#e4cbe8',
40-
Q7: '#d0afd6',
40+
Q7: '#ddbbe6',
4141
Q6: '#d9afe5',
4242
Q5: '#f7cc52',
4343
Q4: '#f1dd72',
44-
Q3: '#c8e389',
45-
Q2: '#97d093',
46-
Q1: '#73d091',
44+
Q3: '#cde030',
45+
Q2: '#6dd452',
46+
Q1: '#41c7ad',
4747
D1: '#1c85b6',
4848
D2: '#7f36be',
4949
D3: '#e68e2e',

0 commit comments

Comments
 (0)