개발/ASP.NET

[Web App/MVC] TailWind CSS 사용해서 Progress 만들기

향포레스트 2023. 10. 27. 02:32
728x90

도전

progress 는 사용하기 좋아하지만 CSS로 직접 스타일을 만들어서 사용해 본 적은 없었습니다. 라이브러리나 UI 개발 도구를 많이 사용했었는데, tailwind css의 속성 외울 겸 만들어보기로 마음먹었습니다. 🏁

계획

  • 베이스가 될 긴 막대기 만든다.
  • 각 아이템의 카운트를 센다.
  • 활성화 아이템을 총 아이템의 개수로 나눠서 %를 구한다.
  • 베이스 긴 막대기를 10개의 구역으로 나눈다.
  • 구한 %값 의 10의 자리 구역만큼 색칠한다.

Tailwind CSS 설정

width 100% 10등분 옵션 설정하기

기본은 4등분, 5등분, 6등분, 12등분 가능하지만 10등분은 없어서 구성 파일에 추가하였습니다.

tailwind.config.js

module.exports = {

    theme: {

        extend: {

            width: {

                '1/10': '10%',

                '2/10': '20%',

                '3/10': '30%',

                '4/10': '40%',

                '5/10': '50%',

                '6/10': '60%',

                '7/10': '70%',

                '8/10': '80%',

                '9/10': '90%',

                '10/10': '100%',

            }

        },

    },

    plugins: [],

}

wwwroot 경로에 html 파일 만들기

유틸리티 클래스를 동적으로 만들면 생성되지 않아서 사용될 유틸리티 클래스를 정적 문자열로 미리 작성할 html을 만들고 tailwind.config.js의 content에 추가하였습니다.

tailwind.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
</head>
<body>
    <div class="hidden">
        <div class="w-1/10"></div>
        <div class="w-2/10"></div>
        <div class="w-3/10"></div>
        <div class="w-4/10"></div>
        <div class="w-5/10"></div>
        <div class="w-6/10"></div>
        <div class="w-7/10"></div>
        <div class="w-8/10"></div>
        <div class="w-9/10"></div>
        <div class="w-10/10"></div>
    </div>
</body>
</html>

tailwind.config.js

module.exports = {

    content: [

        "./wwwroot/lib/tailwind/**/*.html",

    ],

}

ASP.NET Core MVC

ViewModel

SP를 사용할까 싶었지만, Entity 데이터 집계와 연산 처리 결과의 ViewModel를 만들어서 사용하였습니다.

public class ProjectIndexViewModel
{
    public int WorkCount { get; set; }
    public int WorkWebCount { get; set; }

    public int WorkWebProgress { get; set; }

    public int WorkApplicationCount { get; set; }
    public int WorkApplicationProgress { get; set; }

    public int ToyCount { get; set; }
    public int ToyWebCount { get; set; }
    public int ToyWebProgress { get; set; }
    public int ToyApplicationCount { get; set; }
    public int ToyApplicationProgress { get; set; }
}

Controller

public IActionResult Index()
{
    // ViewModel 생성
    ProjectIndexViewModel viewModel = new ProjectIndexViewModel();

    // 아이템 집계
    viewModel.WorkCount = _context.BackgroundProjects.Where(p => p.Project == "WORK").Count();
    viewModel.WorkWebCount = _context.BackgroundProjects.Where(p => p.Project == "WORK" && p.Output == "Web").Count();
    viewModel.WorkApplicationCount = _context.BackgroundProjects.Where(p => p.Project == "WORK" && p.Output == "Application").Count();

    viewModel.ToyCount = _context.BackgroundProjects.Where(p => p.Project == "TOY").Count();
    viewModel.ToyWebCount = _context.BackgroundProjects.Where(p => p.Project == "TOY" && p.Output == "Web").Count();
    viewModel.ToyApplicationCount = _context.BackgroundProjects.Where(p => p.Project == "TOY" && p.Output == "Application").Count();

    // 연산
    if (viewModel.WorkCount > 0) 
    {
        int workWebPercentage = (int)Math.Round((double)viewModel.WorkWebCount / viewModel.WorkCount * 100);
        int workApplicationPercentage = (int)Math.Round((double)viewModel.WorkApplicationCount / viewModel.WorkCount * 100);
        viewModel.WorkWebProgress = workWebPercentage / 10;
        viewModel.WorkApplicationProgress = workApplicationPercentage / 10;
    }

    if (viewModel.ToyCount > 0)
    {
        int toyWebPercentage = (int)Math.Round((double)viewModel.ToyWebCount / viewModel.ToyCount * 100);
        int toyAppPercentage = (int)Math.Round((double)viewModel.ToyApplicationCount / viewModel.ToyCount * 100);
        viewModel.ToyWebProgress = toyWebPercentage / 10;
        viewModel.ToyApplicationProgress = toyAppPercentage / 10;
    }

    return View(viewModel);
}

View

 <div class="w-full h-5 bg-gray-200 rounded-md">
     <div class="relative @(Model.ToyWebCount == 0 ? "w-0" : $"w-{Model.ToyWebProgress.ToString()}/10") h-5 bg-yellow-500 @(Model.ToyWebProgress == 10 ? "rounded-md" : "rounded-s-md")">
         @if (Model.ToyWebProgress > 1)
         {
             <div class="absolute text-sm text-center text-white transform -translate-x-1/2 -translate-y-1/2 top-1/2 left-1/2">@Model.ToyWebCount 개</div>
         }
     </div>
 </div>

구현 화면

마치며

처음에는 속성을 사용하지 않으면 빌드된 css에 생기지 않고, @Model.value 를 이용해서 동적 문자열로 생성되겠지 했지만 tailwind 엔진이 인식하지 않아서 정적 문자열로만 만들 수 있다면 과연 유용할까 싶었는데, html 파일에 모아두고 사용하면 이 것도 꽤 괜찮겠다 싶었습니다.

tailwind css 속성에 익숙해질수록 와 괜찮은데? 싶다가도 View 페이지에서 삼단논리연산을 사용하면 인라인이 아주 길어지는데 tailwind css까지 더 해지니 아주 가로 스크롤이 길어지는 모습을 보니..... 😱 그렇지만 꽤 재미있습니다.

728x90