Files
dredgenews/resources/js/pages/Settings/Index.vue
T
dredgy 439139a057
linter / quality (push) Has been cancelled
tests / ci (8.3) (push) Has been cancelled
tests / ci (8.4) (push) Has been cancelled
tests / ci (8.5) (push) Has been cancelled
Done
2026-07-04 23:09:00 +10:00

199 lines
7.2 KiB
Vue

<script setup lang="ts">
import { Head, router } from '@inertiajs/vue3';
import { route } from 'ziggy-js';
import { computed, ref } from 'vue';
import MainLayout from '@/layouts/MainLayout.vue';
import SectionHeading from '@/components/SectionHeading.vue';
import CategoryDialog from '@/components/Settings/Categories/CategoryDialog.vue';
import type { Category, Feed } from '@/types/types';
defineOptions({ layout: MainLayout });
const props = defineProps<{
categories: Category[];
}>();
const dialogOpen = ref(false);
const editingCategory = ref<Category | null>(null);
const dialogDefaultParentId = ref<number | null>(null);
const parentOptions = computed(() =>
props.categories.map((c) => ({ title: c.title, value: c.id })),
);
const openCreate = (parentId: number | null = null) => {
editingCategory.value = null;
dialogDefaultParentId.value = parentId;
dialogOpen.value = true;
};
const openEdit = (category: Category) => {
editingCategory.value = category;
dialogOpen.value = true;
};
const destroy = (category: Category) => {
if (
!confirm(
`Delete "${category.title}"? This also deletes its subcategories and feeds.`,
)
)
return;
router.delete(route('categories.destroy', category.id), {
preserveScroll: true,
});
};
const feedLabel = (feed: Feed) => feed.type.toUpperCase();
</script>
<template>
<Head title="Feeds" />
<VContainer class="py-8" style="max-width: 720px">
<div class="d-flex align-center justify-space-between mb-6">
<SectionHeading
eyebrow="Settings"
title="Feed categories"
subtitle="Organize the RSS feeds you follow into categories and subcategories."
/>
<VBtn color="primary" @click="openCreate()">New category</VBtn>
</div>
<p v-if="!categories.length" class="text-body-2 text-medium-emphasis">
No categories yet. Create one to start adding feeds.
</p>
<VCard
v-for="category in categories"
:key="category.id"
variant="outlined"
class="mb-4"
>
<VCardText class="pa-4">
<div class="d-flex align-start justify-space-between">
<div>
<h3 class="text-h6 font-weight-bold mb-1">
{{ category.title }}
</h3>
<p
v-if="category.description"
class="text-body-2 text-medium-emphasis mb-2"
>
{{ category.description }}
</p>
<div
v-for="feed in category.feeds"
:key="feed.id"
class="d-flex align-center ga-2 mb-1"
>
<span class="text-caption text-medium-emphasis">{{
feed.url
}}</span>
<VChip size="x-small" variant="outlined">{{
feedLabel(feed)
}}</VChip>
<VChip
v-if="feed.paywall"
size="x-small"
color="warning"
variant="outlined"
>
Paywalled
</VChip>
</div>
</div>
<div class="d-flex ga-1">
<VBtn
icon="mdi-pencil"
size="small"
variant="text"
@click="openEdit(category)"
/>
<VBtn
icon="mdi-delete"
size="small"
variant="text"
@click="destroy(category)"
/>
</div>
</div>
<VDivider v-if="category.children?.length" class="my-4" />
<div
v-for="child in category.children"
:key="child.id"
class="mb-3 ml-4"
>
<div class="d-flex align-start justify-space-between">
<div>
<h4 class="text-subtitle-1 font-weight-medium mb-1">
{{ child.title }}
</h4>
<p
v-if="child.description"
class="text-body-2 text-medium-emphasis mb-2"
>
{{ child.description }}
</p>
<div
v-for="feed in child.feeds"
:key="feed.id"
class="d-flex align-center ga-2 mb-1"
>
<span
class="text-caption text-medium-emphasis"
>{{ feed.url }}</span
>
<VChip size="x-small" variant="outlined">{{
feedLabel(feed)
}}</VChip>
<VChip
v-if="feed.paywall"
size="x-small"
color="warning"
variant="outlined"
>
Paywalled
</VChip>
</div>
</div>
<div class="d-flex ga-1">
<VBtn
icon="mdi-pencil"
size="small"
variant="text"
@click="openEdit(child)"
/>
<VBtn
icon="mdi-delete"
size="small"
variant="text"
@click="destroy(child)"
/>
</div>
</div>
</div>
<VBtn
variant="text"
size="small"
color="primary"
class="ml-4"
@click="openCreate(category.id)"
>
Add subcategory
</VBtn>
</VCardText>
</VCard>
<CategoryDialog
v-model="dialogOpen"
:category="editingCategory"
:parent-options="parentOptions"
:default-parent-id="dialogDefaultParentId"
/>
</VContainer>
</template>