Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes and extensions #357

Merged
merged 2 commits into from
Dec 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/utils/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,10 @@ export const toTitleCase = (str: string): string => {
});
return r;
};

export const isRatingBelow = (rating: string, ratingToCompare: string): boolean => {
const ratings = ["SUS", "OBS", "S1", "S2", "S3", "C1", "C3", "I1", "I3", "SUP", "ADM"];
ratings[-1] = "INA";

return ratings.indexOf(rating) < ratings.indexOf(ratingToCompare);
};
101 changes: 84 additions & 17 deletions src/views/pages/ActivityPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@
<div v-if="loading < 3" class="flex mt-4">Loading... {{ loading }} month(s) loaded.</div>
<div v-else class="flex mt-4">
<table class="w-full">
<thead class="border-b-2 dark:border-gray-800">
<thead class="border-b-2 dark:border-neutral-800">
<tr>
<th class="text-left">Name<br />CID (Rating)</th>
<th>{{ months[4] }}</th>
<th>{{ months[3] }}</th>
<th>{{ months[2] }}</th>
<th>{{ months[1] }}</th>
<th>{{ months[0] }}</th>
<th class="text-left border-r-2 dark:border-neutral-800">Name<br />CID (Rating)</th>
<th class="border-r-1 dark:border-neutral-800">{{ months[4] }}</th>
<th class="border-r-1 dark:border-neutral-800">{{ months[3] }}</th>
<th class="border-r-1 dark:border-neutral-800">{{ months[2] }}</th>
<th class="border-r-1 dark:border-neutral-800">{{ months[1] }}</th>
<th class="border-r-1 dark:border-neutral-800">{{ months[0] }}</th>
<th class="border-l-2 dark:border-neutral-800">Controller Total</th>
</tr>
</thead>
<tbody>
Expand All @@ -22,25 +23,54 @@
class="hover:dark:bg-zinc-800 hover:bg-zinc-300 hover:cursor-pointer"
@click="goToUser(c.cid)"
>
<td class="py-2 border-b-1 dark:border-gray-900">
<td class="py-2 border-b-1 dark:border-neutral-800 border-r-2 dark:border-neutral-800">
{{ c.first_name }} {{ c.last_name }} ({{ c.operating_initials || "none" }})<br />
{{ c.cid }} ({{ c.rating }})
</td>
<td class="text-center py-2 border-b-1 dark:border-gray-900">
<td class="text-center py-2 border-b-1 border-r-1 dark:border-neutral-800">
{{ getHours(minus4.find((c2) => c2.cid === c.cid)) }}
<i :class="getCrown(c, minus4)" />
</td>
<td class="text-center py-2 border-b-1 dark:border-gray-900">
<td class="text-center py-2 border-b-1 border-r-1 dark:border-neutral-800">
{{ getHours(minus3.find((c2) => c2.cid === c.cid)) }}
<i :class="getCrown(c, minus3)" />
</td>
<td class="text-center py-2 border-b-1 dark:border-gray-900">
<td class="text-center py-2 border-b-1 border-r-1 dark:border-neutral-800">
{{ getHours(minus2.find((c2) => c2.cid === c.cid)) }}
<i :class="getCrown(c, minus2)" />
</td>
<td class="text-center py-2 border-b-1 dark:border-gray-900">
<td class="text-center py-2 border-b-1 border-r-1 dark:border-neutral-800">
{{ getHours(minus1.find((c1) => c1.cid === c.cid)) }}
<i :class="getCrown(c, minus1)" />
</td>
<td class="text-center py-2 border-b-1 dark:border-neutral-800">
{{ getHours(c) }}
<i :class="getCrown(c, curMonth)" />
</td>
<td class="text-center py-2 border-b-1 dark:border-neutral-800 border-l-2">
{{
getSum([
minus4.find((c2) => c2.cid === c.cid),
minus3.find((c2) => c2.cid === c.cid),
minus2.find((c2) => c2.cid === c.cid),
minus1.find((c2) => c2.cid === c.cid),
c,
])
}}
</td>
<td class="text-center py-2 border-b-1 dark:border-gray-900">{{ getHours(c) }}</td>
</tr>
</tbody>
<tfoot>
<tr>
<th class="text-left py-2 border-r-2 border-t-2 dark:border-neutral-800">Total Hours</th>
<th class="py-2 border-r-1 border-t-2 dark:border-neutral-800">{{ getSum(minus4) }}</th>
<th class="py-2 border-r-1 border-t-2 dark:border-neutral-800">{{ getSum(minus3) }}</th>
<th class="py-2 border-r-1 border-t-2 dark:border-neutral-800">{{ getSum(minus2) }}</th>
<th class="py-2 border-r-1 border-t-2 dark:border-neutral-800">{{ getSum(minus1) }}</th>
<th class="py-2 border-r-1 border-t-2 dark:border-neutral-800">{{ getSum(curMonth) }}</th>
<th class="border-l-2 border-t-2 dark:border-neutral-800 py-2"></th>
</tr>
</tfoot>
</table>
</div>
</template>
Expand Down Expand Up @@ -77,16 +107,53 @@ const monthNames = [
"December",
];

const formatSecs = (seconds: number): string => {
const hours = Math.floor(seconds / 3600);
const minutes = Math.floor((seconds % 3600) / 60);

if (hours === 0 && minutes === 0) return "";

return `${String(hours).padStart(1, "0")}:${String(minutes).padStart(2, "0")}`;
};

const getHours = (controller: ControllerStats | undefined): string => {
if (!controller) return "";

const secs = controller.cab + controller.terminal + controller.enroute;
const hours = Math.floor(secs / 3600);
const minutes = Math.floor((secs % 3600) / 60);

if (hours === 0 && minutes === 0) return "";
return formatSecs(secs);
};

const getSum = (stats: (ControllerStats | undefined)[]): string => {
if (!stats) return "";

let sum = 0;
stats.forEach((c) => {
if (!c) return;
sum += c.cab + c.terminal + c.enroute;
});
return formatSecs(sum);
};

const getCrown = (controller: ControllerStats | undefined, stats: ControllerStats[]): string => {
if (!controller || !stats) return "hidden";

// Copy stats into new array
const sorted: ControllerStats[] = stats.slice().sort((a: ControllerStats, b: ControllerStats) => {
return b.cab + b.terminal + b.enroute - (a.cab + a.terminal + a.enroute);
});

if (sorted.length === 0) return "hidden";

if (sorted[0].cid === controller.cid) {
return "fa-solid fa-trophy text-alaska-gold";
} else if (sorted[1].cid === controller.cid) {
return "fa-solid fa-trophy text-zinc-500";
} else if (sorted[2].cid === controller.cid) {
return "fa-solid fa-trophy text-amber-700";
}

return `${String(hours).padStart(2, "0")}h ${String(minutes).padStart(2, "0")}m`;
return "hidden";
};

const goToUser = (cid: string | number): void => {
Expand Down
11 changes: 10 additions & 1 deletion src/views/pages/VisitingApplication.vue
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,16 @@
you will receive an email with the outcome of your application after it has been reviewed. Please allow up to 7
days to review your application before contacting staff.
</p>
<div v-if="!applying && !error">
<div v-if="!applying && !error && !isRatingBelow(fac.minVisitorRating, userStore.user?.rating)">
<button class="btn" :class="primaryHover" type="button" @click="apply">
<i class="fa fa-paper-plane" /> Apply
</button>
</div>
<div v-else-if="isRatingBelow(fac.minVisitorRating, userStore.user?.rating)">
<p>
You do not meet the minimum rating requirement of {{ fac.minVisitorRating }} to apply for visiting status.
</p>
</div>
<div v-else-if="applying && !error">
<p>Submitting application...</p>
</div>
Expand All @@ -44,6 +49,9 @@
<li>You already have an outstanding visiting application.</li>
<li>You do not meet the eligibility requirements as listed above.</li>
<li>You are already a member of this facility.</li>
<li>
You are apart of VATUSA and assigned to the ZAE subdivision. You <b>must</b> have a home subdivision first.
</li>
</ul>
<p>The error we got from the backend was: {{ error }}</p>
<p>If you believe this is an error, please contact the facility staff for guidance.</p>
Expand Down Expand Up @@ -108,6 +116,7 @@ import { onMounted, Ref, ref } from "vue";
import Alert from "@/components/Alert.vue";
import { AxiosResponse } from "axios";
import fac from "@/facility";
import { isRatingBelow } from "@/utils/helpers";
import { primaryHover } from "@/utils/colors";
import Spinner from "@/components/Spinner.vue";
import useUserStore from "@/stores/users";
Expand Down
2 changes: 1 addition & 1 deletion src/views/partials/events/Positions.vue
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ const toggleAssignDropdown = (id: number): void => {

const enroutePositions = computed(() => {
if (props.positions) {
return props.positions.filter((pos) => pos.position.includes("_CTR"));
return props.positions.filter((pos) => pos.position.includes("_CTR") || pos.position.includes("_FSS"));
}
return [];
});
Expand Down
4 changes: 4 additions & 0 deletions src/views/partials/roster/ControllerActions.vue
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,10 @@ const focusRemoval = (): void => {
const addVisitor = async (): Promise<void> => {
// This shouldn't be possible, in theory...
if (props.controller.controller_type !== "none") {
// eslint-disable-next-line no-console
console.log("Controller is not controller_type=none.");
// eslint-disable-next-line no-console
console.log(props.controller);
return;
}

Expand Down